CFNetwork

RSS for tag

Access network services and handle changes in network configurations using CFNetwork.

CFNetwork Documentation

Pinned Posts

Posts under CFNetwork tag

130 Posts
Sort by:
Post marked as solved
2 Replies
452 Views
Are there any drawbacks (e.g. slower request) by setting assumesHTTP3Capable to true if the server doesn't support it? Is it OK to set it globally in the app for all URLRequests or it should be set depending on to which server the app makes the request? Thanks!
Posted
by bastawa.
Last updated
.
Post not yet marked as solved
1 Replies
457 Views
I'm using Firebase Auth and Firestore on my app. When I already signed in, my code in init() function workes fine and my screens automatically updated when data load. But when I first sign in, I get The operation couldn’t be completed. (NSURLErrorDomain error -1011.) error and the rest of the code dont work as it should be. What is the issue and how can I solve it?
Posted
by sloutales.
Last updated
.
Post not yet marked as solved
1 Replies
317 Views
I'm unable to set the "secure" property of HTTPCookieProperty (for initializing HTTPCookie) to false. tried: .secure: "FALSE" .secure: "false" .secure: false but all of above resulted in "cookie.isSecure" being true. The only thing that worked was not providing the field at all (which made the property default to false). Seems like a niche bug?
Posted
by jcp_jcp.
Last updated
.
Post not yet marked as solved
3 Replies
1.2k Views
I have an app which uses URLSession-based networking and URLCache for storing network requests on disk. I noticed that when the storage size of URLCache reaches the diskCapacity, the eviction strategy seems to be to remove all entries, which is a problem in my use case. So I decided to write an URLCache subclass which would provide a custom storage for cached responses and which would implement LRU eviction strategy with better control. As URLCache's documentation states, subclassing for this purpose should be supported: The URLCache class is meant to be used as-is, but you can subclass it when you have specific needs. For example, you might want to screen which responses are cached, or reimplement the storage mechanism for security or other reasons. However, I ran into problems with trying to use this new URLCache subclass with URLSession networking. I have a test resource which I fetch using HTTP GET. The response headers contain: Cache-Control: public, max-age=30 Etag: <some-value> When using the standard, non-subclassed URLCache, the first request loads the data from network as expected (verified with HTTP proxy). The second request doesn't go to the network, if done within first 30 seconds, as expected. Subsequent requests after 30 seconds cause conditional GETs with Etag, as expected. When using a URLCache subclass, all requests load the data from network - max-age doesn't seem to matter, and no conditional GETs are made. It seems that the URLCache does something special to the CachedURLResponse instances after they're loaded from its internal storage, and this something affects how URLSession handles the HTTP caching logic. What am I missing here? I've written a very minimal URLCache implementation to demonstrate this problem. This class stores and loads CachedURLResponse instances using NSKeyedArchiver / NSKeyedUnarchiver, and it supports only zero or one response. Note that there are no calls to super - this is by design, since I want to use my own storage. Here's the implementation: class CustomURLCache: URLCache { let cachedResponseFileURL = URL(filePath: NSTemporaryDirectory().appending("entry.data")) // MARK: Internal storage func read() -> CachedURLResponse? { guard let data = try? Data(contentsOf: cachedResponseFileURL) else { return nil } return try! NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as! CachedURLResponse } func store(_ cachedResponse: CachedURLResponse) { try! (try! NSKeyedArchiver.archivedData(withRootObject: cachedResponse, requiringSecureCoding: false)).write(to: cachedResponseFileURL) } // MARK: URLCache Overrides override func cachedResponse(for request: URLRequest) -> CachedURLResponse? { read() } override func getCachedResponse(for dataTask: URLSessionDataTask, completionHandler: @escaping (CachedURLResponse?) -> Void) { guard let response = read() else { completionHandler(nil) return } completionHandler(response) } override func storeCachedResponse(_ cachedResponse: CachedURLResponse, for request: URLRequest) { store(cachedResponse) } override func storeCachedResponse(_ cachedResponse: CachedURLResponse, for dataTask: URLSessionDataTask) { store(cachedResponse) } } My test case: func test() { let useEvictingCache = false let config = URLSessionConfiguration.default if useEvictingCache { config.urlCache = CustomURLCache() } else { config.urlCache = URLCache(memoryCapacity: 0, diskCapacity: 1024 * 1024 * 100) } self.urlSession = URLSession(configuration: config) let url = URL(string: "https://example.com/my-test-resource")! self.urlSession?.dataTask(with: URLRequest(url: url), completionHandler: { data, response, error in if let data { print("GOT DATA with \(data.count) bytes") } else if let error { print("GOT ERROR \(error)") } }).resume() }
Posted
by nzhuk.
Last updated
.
Post not yet marked as solved
1 Replies
289 Views
I am currently implementing an upload flow that utilizes a URLSession with a background configuration to allow the upload to continue running when the application is suspended or terminated by the system. When the upload has completed, and the app is launched/woken up in the backend to respond to the upload task result, I need to make an additional data request to inform the backend that the upload has completed to trigger additional work. I am attempting to do this by making the data request and waiting for it to finish before calling the background events completion handler delivered to the AppDelegate. However, the data request never completes while in the background, but will receive a result when the app is brought to the foreground. Often the result of this data request will be a failure: Error Domain=NSURLErrorDomain Code=-997 "Lost connection to background transfer service" or Error Domain=NSURLErrorDomain Code=-999 "canceled" I understand that a URLSession with a background configuration will reject data tasks when the app is suspended or terminated. However, I am attempting to use a non-background configured network session for the data request while the application is running in the background, before the application is suspended again. Is it not possible to make additional data requests when the app is launched/woken up in the background after a background upload is completed?
Posted Last updated
.
Post not yet marked as solved
6 Replies
844 Views
To download files, we have two NSURLSession objects. One configured for foreground downloads and one for background downloads. Initially, we download user-requested files in the foreground using downloadTaskWithRequest, because foreground downloads are faster than background downloads. We then also start a background task for each download using beginBackgroundTaskWithName:expirationHandler:. This background task's expiration handler starts a background download if the download didn't complete in the foreground. It cancels the foreground download with resume data using cancelByProducingResumeData. A background download task is then started using downloadTaskWithResumeData. Now, testing has shown that background download tasks resume correctly (the urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:) callback is called by iOS) if the background task is started immediately. However, iOS can decide to start these background download tasks later. As a sidenote, the isDiscretionary property of our background download session is set to the default, which should be false. The issue we have is that background downloads that are resumed several minutes (6,5 minutes in the session I'm currently looking at) after their original foreground download was cancelled, are not resumed properly. They download the remaining part of the file, but the first part that was downloaded in the foreground is lost. What could have happened? Perhaps the temporary file has been deleted in the meantime? Is there some way to maintain this file or detect this case?
Posted
by p_b_omta.
Last updated
.
Post not yet marked as solved
1 Replies
422 Views
Hello! I'm working on VLC, that is a multimedia playback app available for any platform. Among many things, we support discovery of servers on the local network using Bonjour, UPnP and NETBIOS with consecutive connections to those servers for media playback purposes. Additionally, we allow connections to unicast and multicast streams based on any domain name or IP (i.e. "rtsp://207.254.***.***"). Discovery of the mentioned services works very well with the Multicast entitlement along with NSLocalNetworkUsageDescription also on iOS 17. According to documentation, iOS 17 prohibits any IP based connections by default, which breaks the entire functionality mentioned above that was previously enabled by including the NSAllowsArbitraryLoads key with the value TRUE in Info.plist. We amended the Info.plist with the following configuration and still fail to connect to hosts in that IP range. <key>NSAllowsLocalNetworking</key> <true/> <key>NSExceptionDomains</key> <dict> <key>192.168.0.0/24</key> <dict> <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> <true/> <key>NSIncludesSubdomains</key> <true/> <key>NSExceptionRequiresForwardSecrecy</key> <false/> <key>NSExceptionAllowsInsecureHTTPLoads</key> <true/> <key>NSExceptionAllowsLocalNetworking</key> <true/> </dict> </dict> Additionally, there does not seem to be a viable, publicly documented solution to connect to any server on the internet based on an IP address. Further, the process for IPv6 seems unclear. Any help how to solve this so we can transition to the iOS/tvOS 17 SDK in time would be very much appreciated.
Posted Last updated
.
Post marked as solved
23 Replies
2.6k Views
We're seeing server trust failures with iOS 17 that we don't see with iOS 16, particularly in debugging, when we build with Xcode 15. We handle func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -&gt; Void) and choose to deal with recoverable server trust failures of particular kinds ourselves. After our checks we end up calling the completion handler: let credential = URLCredential(trust: serverTrust) completionHandler(.useCredential, credential) And everything continues. This is working on macOS Venture and earlier and iOS 16 and earlier. It also works if we install our current release build on iOS 17. If we build with Xcode 15 and test on iOS 17 then calling the completion handler with .useCredential ends up failing with a -1200 error, and a message about a recoverable trust failure. Has anyone else seen this behavior? Does anyone know if this is related to just Xcode 15, or to Xcode 15 + an interaction with iOS 17? Maybe the SDKs used with Xcode 15 are being stricter? In any case it would seem that saying .useCredential should cause it to .use the credential...
Posted
by kbrock.
Last updated
.
Post not yet marked as solved
9 Replies
855 Views
One of our client has contacted us with the following error : Task .&amp;lt;3&amp;gt; request https:URL is NOT allowed to set HSTS for main doc (null) Th request is sent from our SDK. According to the client it happens only on Vision Pro. All our requests to the server on the SDK side are https. The serve has the following header: X-Content-Type-Options X-Frame-Options Strict-Transport-Security Can somebody share some insight?
Posted Last updated
.
Post not yet marked as solved
0 Replies
2.0k Views
General: TN3151 Choosing the right networking API Networking Overview document — Despite the fact that this is in the archive, this is still really useful. TLS for App Developers DevForums post Choosing a Network Debugging Tool documentation WWDC 2019 Session 712 Advances in Networking, Part 1 — This explains the concept of constrained networking, which is Apple’s preferred solution to questions like How do I check whether I’m on Wi-Fi? TN3135 Low-level networking on watchOS Adapt to changing network conditions tech talk Foundation networking: DevForums tags: Foundation, CFNetwork URL Loading System documentation — NSURLSession, or URLSession in Swift, is the recommended API for HTTP[S] on Apple platforms. Network framework: DevForums tag: Network Network framework documentation — Network framework is the recommended API for TCP, UDP, and QUIC on Apple platforms. Network Extension (including Wi-Fi on iOS): See Network Extension Resources Wi-Fi Fundamentals Wi-Fi on macOS: DevForums tag: Core WLAN Core WLAN framework documentation Wi-Fi Fundamentals Secure networking: DevForums tags: Security Apple Platform Security support document Preventing Insecure Network Connections documentation — This is all about App Transport Security (ATS). Available trusted root certificates for Apple operating systems support article Requirements for trusted certificates in iOS 13 and macOS 10.15 support article About upcoming limits on trusted certificates support article Apple’s Certificate Transparency policy support article Technote 2232 HTTPS Server Trust Evaluation Technote 2326 Creating Certificates for TLS Testing QA1948 HTTPS and Test Servers Miscellaneous: More network-related DevForums tags: 5G, QUIC, Bonjour On FTP DevForums post Using the Multicast Networking Additional Capability DevForums post Investigating Network Latency Problems DevForums post Local Network Privacy FAQ DevForums post Extra-ordinary Networking DevForums post Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com"
Posted
by eskimo.
Last updated
.
Post not yet marked as solved
4 Replies
384 Views
I'm having an issue with showing progress in a upload task. I have created a local express app to test it's behavior. But progress / delegate always throughs the same results. I'm also conforming to URLSessionTaskDelegate. This is the way I configure URLSession it's always .default private lazy var session: URLSession = { .init( configuration: self.configuration, delegate: self, delegateQueue: OperationQueue.main ) }() private var observation: NSKeyValueObservation? Then I call it using this func and convert it into a publisher func loadData1(path: String, method: RequestMethod, params: [String: String]) -&gt; AnyPublisher&lt;Data, Error&gt; { let publisher = PassthroughSubject&lt;Data, Error&gt;() guard let imageUrl = Bundle.main.url(forResource: "G0056773", withExtension: "JPG"), let imageData = try? Data(contentsOf: imageUrl) else { return Fail(error: NSError(domain: "com.test.main", code: 1000)).eraseToAnyPublisher() } var request = URLRequest(url: URL(string: "http://localhost:3000/")!) request.httpMethod = "POST" let data = request.createFileUploadBody(parameters: [:], boundary: UUID().uuidString, data: imageData, mimeType: "image/jpeg", fileName: "video") let task = session.uploadTask(with: request, from: data) { data, response, error in if let error = error { return publisher.send(completion: .failure(error)) } guard let response = response as? HTTPURLResponse else { return publisher.send(completion: .failure(ServiceError.other)) } guard 200..&lt;300 ~= response.statusCode else { return publisher.send(completion: .failure(ServiceError.other)) } guard let data = data else { return publisher.send(completion: .failure(ServiceError.custom("No data"))) } return publisher.send(data) } observation = task.progress.observe(\.fractionCompleted) { progress, _ in print("progress: ", progress.totalUnitCount) print("progress: ", progress.completedUnitCount) print("progress: ", progress.fractionCompleted) print("***********************************************") } task.resume() return publisher.eraseToAnyPublisher() } request.createFileUploadBody is just an extension of URLRequest that I have created to create the form data's body. Delegate func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) { print(bytesSent) print(totalBytesSent) print(totalBytesExpectedToSend) print("*********************************************") } No matter how big or small is the file that I'm uploading I always get the same results. The delegate is only called once. And the progress is also always the same. progress: 100 progress: 0 progress: 0.0095 *********************************************** progress: 100 progress: 0 progress: 4.18053577746524e-07 *********************************************** 2272436 2272436 2272436 ********************************************* progress: 100 progress: 95 progress: 0.95 *********************************************** progress: 100 progress: 100 progress: 1.0 *********************************************** ^^^^^^ Output from prints Does anyone knows what might I be doing wrong? Thanks in advance
Posted
by MostaZa.
Last updated
.
Post not yet marked as solved
0 Replies
165 Views
I regularly see folks confused as to which URLSession task types are supported in which session types. Here’s a handy reference: Task Type Standard Background --------- -------- ---------- data, convenience yes no data, delegate yes yes [1] download, convenience yes no download, delegate yes yes upload, convenience yes no upload, delegate, data yes no upload, delegate, stream yes no upload, delegate, file yes yes stream yes no WebSocket yes no In this table: A background session is one created from a configuration that was created with the background(withIdentifier:) method. A standard session is one created from some other configuration, namely default or ephemeral. A convenience task is one created by a Swift async method or a method that takes a completion handler. A delegate task is one created otherwise; these signal their completion by calling the urlSession(_:task:didCompleteWithError:) delegate method. For an upload task, the data, stream, and file modifiers indicate how you specify the HTTP request body. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] While it’s possible to run a data task in a background session, this only works if your app avoids suspension while the request is in flight. This is useful in very rare circumstances [2] that most developers never encounter. [2] The specific situation I’m aware of is when you don’t know whether a request’s response will be big (like a file to download) or small (like a status response). To handle this, you start a data task in the background session and, if the response indicates that it’s large, transform it to a download task in your urlSession(_:dataTask:didReceive:completionHandler:) method. (r. 123084713)
Posted
by eskimo.
Last updated
.
Post not yet marked as solved
0 Replies
263 Views
I am using Relay to connect to nginx server which supports http3 connections for which I get quic_stream_send_create [C1.1.1.1:5] [24e7c30b6b4eb7ba-0000000000001002e2c0e6cb5099cd86ef1f0f7c] unable to create DATAGRAM flow since the peer did not provide max_datagram_frame_size in transport parameters [C1.1.1.1:3] Unable to send 1200 early bytes quic_stream_send_create [C1.1.1.1:5] [24e7c30b6b4eb7ba-0000000000001002e2c0e6cb5099cd86ef1f0f7c] unable to create DATAGRAM flow since the peer did not provide max_datagram_frame_size in transport parameters This is something very simple I have written : ` let relayURL = URL(string: "https://192.168.64.2:8443")! let relayEndpoint = NWEndpoint.url(relayURL) if #available(iOS 17.0, *) { var tlsOptions = NWProtocolTLS.Options() let relayServer = ProxyConfiguration.RelayHop(http3RelayEndpoint: relayEndpoint, tlsOptions: NWProtocolTLS.Options = .init()) let relayConfig = ProxyConfiguration(relayHops: [relayServer]) let config = URLSessionConfiguration.default` config.connectionProxyDictionary = [kCFNetworkProxiesHTTPEnable as AnyHashable: true, kCFNetworkProxiesHTTPProxy as AnyHashable: "192.168.64.2", kCFNetworkProxiesHTTPPort as AnyHashable: 8443, kCFStreamPropertySSLSettings as AnyHashable: sslSettings] config.proxyConfigurations = [relayConfig] // Call addCert to add the certificate to the trust store //addCert(cert: "cert") // Example usage of the custom session let session = makeInsecureURLSession(config: config) let url = URL(string: "https://google.com")! // Example URL let task = session.dataTask(with: url) { data, response, error in // Handle response print("response is \(response)") if let httpResponse = response as? HTTPURLResponse { let protocolUsed = httpResponse.url?.scheme ?? "Unknown" print("Protocol used: \(protocolUsed)") } else { print("Response is not an HTTPURLResponse") } } task.resume()
Posted
by Ankita11.
Last updated
.
Post not yet marked as solved
0 Replies
234 Views
I recently handled a couple of questions about this for DTS, so I thought I’d write it up for the benefit of all. If you have any questions or comments, please put them in a new thread here on DevForums. Tag it with Foundation and CFNetwork so that I see it. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" HTTP authentication challenges with Swift concurrency URLSession has always made it easy to access HTTP resources, but things get even better when you combine that with Swift concurrency. For example: import Foundation func main() async throws { // Set up the request. let url = URL(string: "https://example.com")! let request = URLRequest(url: url) // Run it; this will throw if there’s a transport error. let (body, response) = try await URLSession.shared.data(for: request) // Check for a server-side error. guard let response = response as? HTTPURLResponse, response.statusCode == 200 else { … handle the error … } // Success. … HTTP response headers are in `response.allHeaderFields` … … HTTP response body is in `body` … } try await main() But what happens if you need to handle an HTTP authentication challenge? The current documentation for authentication challenges is very good, but it assumes that you have a session delegate. That doesn’t really mesh well with Swift concurrency. Fortunately there’s an easier way: Pass in a per-task delegate. Consider this slightly updated snippet: let url = URL(string: "https://postman-echo.com/basic-auth")! let request = URLRequest(url: url) let (body, response) = try await URLSession.shared.data(for: request) This fetches a resource, https://postman-echo.com/basic-auth, that requires HTTP Basic authentication. This request fails with a 401 status code because nothing handles that authentication. To fix that, replace the last line with this: let delegate = BasicAuthDelegate(user: "postman", password: "password") let (body, response) = try await URLSession.shared.data(for: request, delegate: delegate) This creates an instance of the BasicAuthDelegate, passing in the user name and password required to handle the challenge. That type implements the URLSessionTaskDelegate protocol like so: final class BasicAuthDelegate: NSObject, URLSessionTaskDelegate { init(user: String, password: String) { self.user = user self.password = password } let user: String let password: String func urlSession( _ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge ) async -> (URLSession.AuthChallengeDisposition, URLCredential?) { // We only care about Basic authentication challenges. guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic else { return (.performDefaultHandling, nil) } // Limit the authentication attempts. guard challenge.previousFailureCount < 2 else { return (.cancelAuthenticationChallenge, nil) } // If all is well, return a credential. let credential = URLCredential(user: user, password: password, persistence: .forSession) return (.useCredential, credential) } } This delegate handles the NSURLAuthenticationMethodHTTPBasic authentication challenge, allowing the overall request to succeed. Now you have the best of both worlds: An easy to use HTTP API With the flexibility to handle authentication challenges This approach isn’t right for all programs, but if you’re just coming up to speed on URLSession it’s a great place to start.
Posted
by eskimo.
Last updated
.
Post not yet marked as solved
0 Replies
338 Views
Hi, I am implementing the HTTP3 Relay server, and testing by the URLSession, let relayEndpoint = NWEndpoint.url(URL(string:"https://localhost:8002")!) let relayServer = ProxyConfiguration.RelayHop( http3RelayEndpoint: relayEndpoint, additionalHTTPHeaderFields: ["Proxy-Authorization":"Basic ***"] ) let relayConfig = ProxyConfiguration(relayHops: [relayServer]) let config = URLSessionConfiguration.default config.proxyConfigurations = [relayConfig] let s = URLSession(configuration: config) I have implemented both the CONNECT method and CONNECT method with :protocol of CONNECT-UDP over HTTP/3. If I enabled CONNECT-UDP only, when I try to connect some HTTP/3 URL like https://quic.aiortc.org/4, it works without problem. And URLSession will use the CONNECT-UDP to connect the UDP channel, throw which the URLSession will do the HTTP/3 request. However, if i enabled both the CONNECT-UDP and CONNECT (for TCP tunnel), the URLSession seems wired. It first try to establish the tunnel for UDP using the CONNECT-UDP method, and then closed it. And finally, it created the TCP tunnel using the CONNECT method. So is there any detailed document for the behavior of the behavior of URLSession with http3RelayEndpoint? Thanks you.
Posted
by lvht.
Last updated
.
Post not yet marked as solved
2 Replies
351 Views
Code snippet below: NSString *host = @"time.google.com"; CFHostRef cfHostRef = CFHostCreateWithName(nil, (__bridge CFStringRef) host); Boolean didLookup = CFHostStartInfoResolution(cfHostRef, kCFHostAddresses, nil); NSLog(@"didLookup=%d", didLookup); CFArrayRef addresses = CFHostGetAddressing(cfHostRef, &didLookup); struct sockaddr *remoteAddr; long count = CFArrayGetCount(addresses); NSLog(@"count=%ld (this should include both ip4 and ip6)", count); for(int i = 0; i < count; i++) { CFDataRef saData = (CFDataRef)CFArrayGetValueAtIndex(addresses, i); remoteAddr = (struct sockaddr*)CFDataGetBytePtr(saData); NSLog(@"family=%d (AF_INET=%d, AF_INET6=%d)",remoteAddr->sa_family, AF_INET, AF_INET6); NSString* addrPretty = nil; switch (remoteAddr->sa_family) { case AF_INET: { char dest[INET_ADDRSTRLEN]; struct sockaddr_in *ip4 = (struct sockaddr_in *) remoteAddr; addrPretty = [NSString stringWithFormat: @"%s", inet_ntop(AF_INET, &ip4->sin_addr, dest, INET_ADDRSTRLEN)]; break; } case AF_INET6: { char dest[INET6_ADDRSTRLEN]; struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *) remoteAddr; addrPretty = [NSString stringWithFormat: @"%s", inet_ntop(AF_INET6, &ip6->sin6_addr, dest, INET6_ADDRSTRLEN)]; break; } default: break; } NSLog(@"addrPretty=%@", addrPretty); } As far as I understand this should print out both IPv4 and IPv6 addresses, but it only does the former. This is as tested on both a simulator and a real device, on different networks. Note that I can traceroute6 -I time.google.com and see IPv6 addresses just fine, and I can also do set q=AAAA in the nslookup prompt and get the expected addresses when performing the query for time.google.com in the same prompt.
Posted
by jantonio.
Last updated
.
Post not yet marked as solved
3 Replies
423 Views
Hi There, I am trying to record a meeting and upload it to AWS server. The recording is in .m4a format and the upload request is a URLSession request. The following code works perfectly for recordings less than 15 mins. But then for greater recordings, it gets stuck Could you please help me out in this? func startRecording() { let audioURL = getAudioURL() let audioSettings = [ AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: 12000, AVNumberOfChannelsKey: 1, AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue ] do { audioRecorder = try AVAudioRecorder(url: audioURL, settings: audioSettings) audioRecorder.delegate = self audioRecorder.record() } catch { finishRecording(success: false) } } func uploadRecordedAudio{ let _ = videoURL.startAccessingSecurityScopedResource() let input = UploadVideoInput(signedUrl: signedUrlResponse, videoUrl: videoURL, fileExtension: "m4a") self.fileExtension = "m4a" uploadService.uploadFile(videoUrl: videoURL, input: input) videoURL.stopAccessingSecurityScopedResource() } func uploadFileWithMultipart(endPoint: UploadEndpoint) { var urlRequest: URLRequest urlRequest = endPoint.urlRequest uploadTask = URLSession.shared.uploadTask(withStreamedRequest: urlRequest) uploadTask?.delegate = self uploadTask?.resume() }
Posted
by snehal-a.
Last updated
.
Post not yet marked as solved
1 Replies
2.5k Views
This post is part of the Local Network Privacy FAQ - https://developer.apple.com/forums/thread/663858. My app presents the local network privacy alert unexpectedly. Is there a way to track down the cause? If the alert is correlated with something you do in your app then you can step through your code to see what triggers it. However, in some cases this won’t help. For example, some third-party libraries automatically run code in your app that triggers the local network privacy alert. One option here is to start removing any third-party libraries from your app until you figure out which one is triggering it, and then raise this issue with the library’s vendor. If you get completely stuck then start a new thread here on DevForums - https://developer.apple.com/forums/ and I’ll try to help out there. Make sure to tag your thread with one of the standard networking tags (Bonjour, CFNetwork, or Network). Back to the FAQ - https://developer.apple.com/forums/thread/663858
Posted
by eskimo.
Last updated
.
Post not yet marked as solved
3 Replies
1.1k Views
I'm trying to set up background HTTP upload requests (syncing files from the user's phone to a server) that trigger periodically in my Swift app. I don't have strict requirements on when this runs (it can happen overnight or throughout the day). I know Apple provides several APIs for background tasks on iOS (beginBackgroundTask, BGAppRefreshTaskRequest, BGProcessingTaskRequest, URLSession upload vs. background session). And I've seen this post on the Apple developer forums that attempts to explain the differences and when to use which - as well as Apple's page on the subject, but it's still not clear to me how a few of these work in practice, and thus which ones I should utilize for my use case. My questions: How should I schedule periodic file upload tasks in the background? I assume I should use BGProcessingTaskRequest, since I don't know exactly how long the task will take (it could be syncing just 1-2 files, or it could be hundreds) and I don't care if it runs overnight How should I ensure foreground tasks are able to complete after closing the app? (i.e. when a user starts a sync manually in the app) From Apple's page on URLSessionUploadTask: "Unlike data tasks, you can use upload tasks to upload content in the background." Does this mean any requests I make using URLSession.shared.upload() will automatically run in the background if the user closes the app? Even with the async/await version, or do I have to use the completionHandler version? Do I need to call beginBackgroundTask if I'm using URLSession.shared.upload() to guarantee I get more time to finish uploads? What about sequential requests (i.e. requests that haven't started yet by the time the app is closed)? Based on this StackOverflow response, it sounds like I may need to trigger all the uploads in parallel beforehand? https://stackoverflow.com/a/53949607/2359478 Should I even consider URLSessionConfiguration.background for my use case? It sounds like it I use beginBackgroundTask and BGProcessingTaskRequest then this may be unnecessary? Thanks!
Posted Last updated
.