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 not yet marked as solved
0 Replies
5.2k Views
Note Much of this content has been rolled into URL Loading System documentation, but I’m leaving this doc here for my own reference. URLSession background sessions are optimised for transferring a small number of large resources. Moreover, it’s best if the transfer is resumable. This design makes the best use of client device resources and the available network bandwidth. If your app runs a lot of tasks in a background session, you should rethink its design. Below you’ll find a number of options you might consider. Most of these options require server-side support. If your server does not have this support, and you can’t add it — perhaps you’re writing a client app for a server you don’t control — you won’t be able to implement these options directly. In that case consider creating your own server that sits between your app and the final server and implements the necessary smarts required to optimise your app’s network usage. If that’s not possible, a final option is to not use a background session but instead take advantage of the BackgroundTasks framework. See BackgroundTasks Framework, below. Basics The basic strategy here is to have the sender (the server for a download, your app for an upload) pack the data into some sort of archive, transfer that archive over the network, and then have the receiver unpack it. There are, however, a number of complications, as described in the subsequent sections. Archive Format The obvious choices for the archive format are zip and tar. macOS has lots of options for handling these formats but none of that support is present on iOS (r. 22151959). OTOH, it’s easy to find third-party libraries to fill in this gap. Incremental Transfers It’s common to have a corpus of data at one end of the connection that you need to replicate at the other. If the data is large, you don’t want to transfer the whole thing every time there’s an update. Consider using the following strategies to deal with this: Catalogue diff — In this approach the receiver first downloads a catalogue from the sender, then diffs its current state against that catalogue, then requests all the things that are missing. Alternatively, the receiver passes a catalogue of what it has to the sender, at which point the sender does the diff and returns the things that are missing. The critical part is that, once the diff has been done, all of the missing resources are transferred in a single archive. The biggest drawback here is resume. If the sender is working with lots of different receivers, each of which has their own unique needs, the sender must keep a lot of unique archives around so it can resume a failed transfer. This can be a serious headache. Versions — In this approach you manage changes to the data as separate versions. The receiver passes the version number it has to the sender, at which point the sender knows exactly what data the receiver needs. This approach requires a bit more structure but it does avoid the above-mentioned problem with resume. The sender only needs to maintain a limited number of version diffs. In fact, you can balance the number of diffs against your desire to reduce network usage: Maintaining a lot of diffs means that you only have to transfer exactly what the receiver needs, while maintaining fewer diffs makes for a simpler server at the cost of a less efficient use of the network. Download versus Upload The discussion so far has applied equally to both downloads and uploads. Historically, however, there was one key difference: URLSession did not support resumable uploads. IMPORTANT Starting with iOS 17, URLSession supports resumable uploads. See WWDC 2023 Session 10006 Build robust and resumable file transfers for the details. The rest of this section assumes that you don’t have access to that support, either because you’re working on an older system or because the server you’re uploading to doesn’t support this feature. When doing a non-resumable upload you have to balance the number of tasks you submit to the session against the negative effects of a transfer failing. For example, if you do a single large upload then it’s annoying if the transfer fails when it’s 99% complete. On the other hand, if you do lots of tiny uploads, you’re working against the URLSession background session design. It is possible to support resumable uploads with sufficient server-side support. For example, you could implement an algorithm like this: Run an initial request to allocate an upload ID. Start the upload with that upload ID. If it completes successfully, you’re done. If it fails, make a request with the upload ID to find out how much the server received. Start a new upload for the remaining data. Indeed, this is kinda how the built-in resumable upload support works. If you’re going to implement something like this, it’s best to implement that protocol. (r. 22323347) BackgroundTasks Framework If you’re unable to use an URLSession background session effectively, you do have an alternative, namely, combining a standard session with the BackgroundTasks framework, and specifically the BGProcessingTaskRequest. This allows you to request extended processing time from the system. Once you’ve been granted that time, use it to run your many small network requests in a standard session. The main drawback to this approach is latency: The system may not grant your request for many hours. Indeed, it’s common for these requests to run overnight, once the user has connected their device to a power source. Background Assets Framework If you’re using URLSession to download assets for your app or game, check out the Background Assets framework. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Revision History 2023-09-27 Added information about the new resumable upload support. Added the Background Assets Framework section. Made significant editorial changes. 2022-01-31 Fixed the formatting and tags. Added a link to the official docs. 2018-03-24 Added the BackgroundTasks Framework section. Other editorial changes. 2015-08-18 First written.
Posted
by
Post not yet marked as solved
0 Replies
27k Views
Debugging code that runs in the background on iOS is tricky because the act of running your app in the debugger affects how it behaves. This is especially true with URLSession background session code. I regularly see folks confused about how to test and debug such code, and this is my attempt to help with that. If you have questions or comments about this, start a new thread and 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" Testing Background Session Code Testing an app that uses a URLSession background session is tricky because of the differences between the test environment and the production environment. This post explains those differences and describes how you can effectively test your background session code. Confusing Behaviours When testing background session code you might encounter four common sources of confusion: When you run your app from Xcode, Xcode installs the app in a new container, meaning that the path to your app changes. Background sessions should deal with this path change correctly, but there have been times in the past where that’s not been the case. Note If you encounter a problem with a background session mishandling a container path change, please report that as a bug. Xcode’s debugger prevents the system from suspending your app. If you run your app from Xcode, or you attach to the process after launch, and then move your app into the background, your app will continue executing in situations where the system would otherwise have suspended it. Simulator may not accurately simulate app suspend and resume. Note This is supposed to work but there have been problems with it in the past (r. 16532261). If you see this problem on modern versions of Xcode, please report it as a bug. When you remove an app from the multitasking UI (aka force quit it), the system interprets that as a strong indication that the app should do no more work in the background, and that includes URLSession background tasks. Testing Recommendations Given the above, my recommendation is that you test your app as follows: Test on a real device, not in Simulator. Run your app from the Home screen rather than running it from Xcode. Don’t use force quit to test the ‘relaunch in the background case’. Doing this avoids all of the issues described above, resulting in a run-time environment that’s much closer to what your users will see. Debugging Background Session Code If you encounter problems that you need to debug, you have two options. The first is to use logging. Your app needs good logging support anyway; without that, it’ll be impossible to debug problems that only show up in the field. Once you’ve taken the time to create this logging, use it to debug problems during development. I recommend that you log to the system log. For more on that, see Your Friend the System Log. If you have a specific problem that you must investigate with the debugger, run your app from the Home screen and then attach to the running process by choosing Debug > Attach to Process in Xcode. Alternatively, use “Wait for executable to be launched” in the Info tab of the Xcode’s scheme editor. IMPORTANT As mentioned above, the debugger prevents your app from suspending. If that’s a problem, you can always detach and then reattach later on. About Force Quit The behaviour of background sessions after a force quit has changed over time: In iOS 7 the background session and all its tasks just ‘disappear’. In iOS 8 and later the background session persists but all of the tasks are cancelled. Note You can use the NSURLErrorBackgroundTaskCancelledReasonKey property of the error to find out why a task was cancelled. Test that your app handles the force quit behaviour of the platforms you support. However, don’t use force quit to test how your app deals with the ‘relaunch in the background case’. The best way to test the ‘relaunch in the background case’ is to have your app terminate itself by calling exit. The system does not interpret this as a force quit, and thus will relaunch your app in the background when your background session needs attention. There two ways to go about this: Simply add a Quit button that calls exit. Add some setting that causes your app to call exit shortly after moving to the background. You’ll need to use a UIApplication background task to prevent your app from being suspended before it gets a chance to quit. IMPORTANT The suggestions above are for testing only. Do not include a Quit button in your final app! This is specifically proscribed by QA1561. Starting From Scratch While bringing up a feature that uses background sessions, it’s often useful to start from a clean slate on launch; this prevents tasks from a previous debugging session confusing the current debugging session. You have a number of options here: If you’re testing in Simulator, Device > Erase All Content and Settings is an excellent way to wipe the slate completely clean. On both Simulator and a real device, you can delete your app. This removes the app, everything in the app’s container, and everything created by the app, including any background sessions. You can also take advantage of the invalidateAndCancel() method, which will cancel any running tasks and then invalidate the session. There are a few ways to use invalidateAndCancel(): During active development it might make sense for your app to call this on launch, guaranteeing that you start with a clean slate every time. Alternatively, you could keep track of your app’s install path and call it on launch if the install path has changed. You might add a ‘hidden’ UI that invalidates the session. This is helpful when you encounter a problem and want to know whether it’s caused by some problem with the background session’s persistent state. Revision History 2023-07-12 Fixed the formatting. Made significant editorial changes. 2018-05-03 Added a discussion of force quit. Also made major editorial changes, restructuring the document to be easy to read. 2015-08-18 First posted. (r. 22323379)
Posted
by
Post not yet marked as solved
0 Replies
6.3k Views
Transport Layer Security (TLS) is the most important security protocol on the Internet today. Most notably, TLS puts the S into HTTPS, adding security to the otherwise insecure HTTP protocol. IMPORTANT TLS is the successor to the Secure Sockets Layer (SSL) protocol. SSL is no longer considered secure and it’s now rarely used in practice, although many folks still say SSL when they mean TLS. TLS is a complex protocol. Much of that complexity is hidden from app developers but there are places where it’s important to understand specific details of the protocol in order to meet your requirements. This post explains the fundamentals of TLS, concentrating on the issues that most often confuse app developers. Note If you’re working on TLS in the local environment, for example, to talk to a Wi-Fi based accessory, see TLS For Accessory Developers. Server Certificates For standard TLS to work the server must have a digital identity, that is, the combination of a certificate and the private key matching the public key embedded in that certificate. TLS Crypto Magic™ ensures that: The client gets a copy of the server’s certificate. The client knows that the server holds the private key matching the public key in that certificate. In a typical TLS handshake the server passes the client a list of certificates, where item 0 is the server’s certificate (the leaf certificate), item N is (optionally) the certificate of the certificate authority that ultimately issued that certificate (the root certificate), and items 1 through N-1 are any intermediate certificates required to build a cryptographic chain of trust from 0 to N. Note The cryptographic chain of trust is established by means of digital signatures. Certificate X in the chain is issued by certificate X+1. The owner of certificate X+1 uses their private key to digitally sign certificate X. The client verifies this signature using the public key embedded in certificate X+1. Eventually this chain terminates in a trusted anchor, that is, a certificate that the client trusts by default. Typically this anchor is a self-signed root certificate from a certificate authority. Note Item N is optional for reasons I’ll explain below. Also, the list of intermediate certificates may be empty (in the case where the root certificate directly issued the leaf certificate) but that’s uncommon for servers in the real world. Once the client gets the server’s certificate, it evaluates trust on that certificate to confirm that it’s talking to the right server. There are three levels of trust evaluation here: Basic X.509 trust evaluation checks that there’s a cryptographic chain of trust from the leaf through the intermediates to a trusted root certificate. The client has a set of trusted root certificates built in (these are from well-known certificate authorities, or CAs), and a site admin can add more via a configuration profile. This step also checks that none of the certificates have expired, and various other more technical criteria (like the Basic Constraints extension). Note This explains why the server does not have to include the root certificate in the list of certificates it passes to the client; the client has to have the root certificate installed if trust evaluation is to succeed. In addition, TLS trust evaluation (per RFC 2818) checks that the DNS name that you connected to matches the DNS name in the certificate. Specifically, the DNS name must be listed in the Subject Alternative Name extension. Note The Subject Alternative Name extension can also contain IP addresses, although that’s a much less well-trodden path. Also, historically it was common to accept DNS names in the Common Name element of the Subject but that is no longer the case on Apple platforms. App Transport Security (ATS) adds its own security checks. Basic X.509 and TLS trust evaluation are done for all TLS connections. ATS is only done on TLS connections made by URLSession and things layered on top URLSession (like WKWebView). In many situations you can override trust evaluation; for details, see Technote 2232 HTTPS Server Trust Evaluation). Such overrides can either tighten or loosen security. For example: You might tighten security by checking that the server certificate was issued by a specific CA. That way, if someone manages to convince a poorly-managed CA to issue them a certificate for your server, you can detect that and fail. You might loosen security by adding your own CA’s root certificate as a trusted anchor. IMPORTANT If you rely on loosened security you have to disable ATS. If you leave ATS enabled, it requires that the default server trust evaluation succeeds regardless of any customisations you do. Mutual TLS The previous section discusses server trust evaluation, which is required for all standard TLS connections. That process describes how the client decides whether to trust the server. Mutual TLS (mTLS) is the opposite of that, that is, it’s the process by which the server decides whether to trust the client. Note mTLS is commonly called client certificate authentication. I avoid that term because of the ongoing confusion between certificates and digital identities. While it’s true that, in mTLS, the server authenticates the client certificate, to set this up on the client you need a digital identity, not a certificate. mTLS authentication is optional. The server must request a certificate from the client and the client may choose to supply one or not (although if the server requests a certificate and the client doesn’t supply one it’s likely that the server will then fail the connection). At the TLS protocol level this works much like it does with the server certificate. For the client to provide this certificate it must apply a digital identity, known as the client identity, to the connection. TLS Crypto Magic™ assures the server that, if it gets a certificate from the client, the client holds the private key associated with that certificate. Where things diverge is in trust evaluation. Trust evaluation of the client certificate is done on the server, and the server uses its own rules to decided whether to trust a specific client certificate. For example: Some servers do basic X.509 trust evaluation and then check that the chain of trust leads to one specific root certificate; that is, a client is trusted if it holds a digital identity whose certificate was issued by a specific CA. Some servers just check the certificate against a list of known trusted client certificates. When the client sends its certificate to the server it actually sends a list of certificates, much as I’ve described above for the server’s certificates. In many cases the client only needs to send item 0, that is, its leaf certificate. That’s because: The server already has the intermediate certificates required to build a chain of trust from that leaf to its root. There’s no point sending the root, as I discussed above in the context of server trust evaluation. However, there are no hard and fast rules here; the server does its client trust evaluation using its own internal logic, and it’s possible that this logic might require the client to present intermediates, or indeed present the root certificate even though it’s typically redundant. If you have problems with this, you’ll have to ask the folks running the server to explain its requirements. Note If you need to send additional certificates to the server, pass them to the certificates parameter of the method you use to create your URLCredential (typically init(identity:certificates:persistence:)). One thing that bears repeating is that trust evaluation of the client certificate is done on the server, not the client. The client doesn’t care whether the client certificate is trusted or not. Rather, it simply passes that certificate the server and it’s up to the server to make that decision. When a server requests a certificate from the client, it may supply a list of acceptable certificate authorities [1]. Safari uses this to filter the list of client identities it presents to the user. If you are building an HTTPS server and find that Safari doesn’t show the expected client identity, make sure you have this configured correctly. If you’re building an iOS app and want to implement a filter like Safari’s, get this list using: The distinguishedNames property, if you’re using URLSession The sec_protocol_metadata_access_distinguished_names routine, if you’re using Network framework [1] See the certificate_authorities field in Section 7.4.4 of RFC 5246, and equivalent features in other TLS versions. Self-Signed Certificates Self-signed certificates are an ongoing source of problems with TLS. There’s only one unequivocally correct place to use a self-signed certificate: the trusted anchor provided by a certificate authority. One place where a self-signed certificate might make sense is in a local environment, that is, securing a connection between peers without any centralised infrastructure. However, depending on the specific circumstances there may be a better option. TLS For Accessory Developers discusses this topic in detail. Finally, it’s common for folks to use self-signed certificates for testing. I’m not a fan of that approach. Rather, I recommend the approach described in QA1948 HTTPS and Test Servers. For advice on how to set that up using just your Mac, see TN2326 Creating Certificates for TLS Testing. TLS Standards RFC 6101 The Secure Sockets Layer (SSL) Protocol Version 3.0 (historic) RFC 2246 The TLS Protocol Version 1.0 RFC 4346 The Transport Layer Security (TLS) Protocol Version 1.1 RFC 5246 The Transport Layer Security (TLS) Protocol Version 1.2 RFC 8446 The Transport Layer Security (TLS) Protocol Version 1.3 RFC 4347 Datagram Transport Layer Security RFC 6347 Datagram Transport Layer Security Version 1.2 RFC 9147 The Datagram Transport Layer Security (DTLS) Protocol Version 1.3 Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Revision History: 2024-03-19 Adopted the term mutual TLS in preference to client certificate authentication throughout, because the latter feeds into the ongoing certificate versus digital identity confusion. Defined the term client identity. Added the Self-Signed Certificates section. Made other minor editorial changes. 2023-02-28 Added an explanation mTLS acceptable certificate authorities. 2022-12-02 Added links to the DTLS RFCs. 2022-08-24 Added links to the TLS RFCs. Made other minor editorial changes. 2022-06-03 Added a link to TLS For Accessory Developers. 2021-02-26 Fixed the formatting. Clarified that ATS only applies to URLSession. Minor editorial changes. 2020-04-17 Updated the discussion of Subject Alternative Name to account for changes in the 2019 OS releases. Minor editorial updates. 2018-10-29 Minor editorial updates. 2016-11-11 First posted.
Posted
by
Post not yet marked as solved
0 Replies
3.3k Views
There are many cases where you want to do long-running network operations in a short-lived app extension. For example, you might be creating a share extension that needs to upload a large image to an Internet server. Doing this correctly is quite tricky. The rest of this post describes some of these pitfalls and explains how to get around them. Just by way of context: Most of the following was written during the iOS 8.1 timeframe, although AFAIK there’s been no specific changes in this space since then. The specific focus here is a share extension, although the behaviour is likely to be similar for other short-lived extensions. I wasn’t using SLComposeServiceViewController, although I have no reason to believe that makes a difference. I was testing on a device, not the simulator. In my experience the simulator is much less likely to terminate a share extension, which affects how things behave as I’ll explain later. My app and its share extension have an app group in common. I started by verifying that this app group was working as expected (using UserDefaults). The URLSession must be in that app group; set this via the sharedContainerIdentifier property of the URLSessionConfiguration object you use to create the session. The app and the share extension must use the same URLSession background session identifier (the value you pass in to background(withIdentifier:) when creating the configuration that you use to create the session). When an URLSession background session is shared like this, it’s critical to understand that the session only allows one process to ‘connect’ to it at a time. If a process is connected to the session and another tries to connect, the second process has its session immediately invalidated with NSURLErrorBackgroundSessionInUseByAnotherProcess. The connected session is the one that receives the session’s delegate callbacks. IMPORTANT If callbacks are generated when no process is connected, the background session resumes (or relaunches) the app rather than the extension. If a process is connected to a session and is then suspended or terminates, the session disconnects internally. If the process was terminated, the reconnection happens when your code creates its URLSession object on next launch. If the process was suspended, the reconnect happens when the app is resumed with the application(_:handleEventsForBackgroundURLSession:completionHandler:) delegate callback (and remember that this is always the app, not the extension, per the previous paragraph). The only way to programmatically disconnect from a session is to invalidate it. The expected behaviour here is that the extension will start an URLSession task and then immediately quit (by calling completeRequest(returningItems:completionHandler:)). The system will then resume (or relaunch) the container app to handle any delegate callbacks. When the system resumes or relaunches the container app to handle background session events, it calls application(_:handleEventsForBackgroundURLSession:completionHandler:). The container app is expected to: Save away the completion handler. Reconnect to the session, if necessary. This involves creating the URLSession object if it doesn’t currently exist. Handle delegate events from that session. Invalidate the session when those events are all done. The app knows this because the session calls the urlSessionDidFinishEvents(forBackgroundURLSession:) delegate callback. Call the completion handler that was saved in step 1. This leaves the app disconnected from the session, so future invocations of the extension don’t have to worry about the NSURLErrorBackgroundSessionInUseByAnotherProcess problem I mentioned earlier. This design works best if each extension hosted by the app has its own shared session. If the app hosts multiple extensions, and they all used the same shared session, they could end up stomping on each other. In my tests I’ve noticed that some annoying behaviour falls out of this design: If you start a task from an extension, it’s non-deterministic as to whether the app or extension gets the ‘did complete’ callback. If the task runs super quickly, the extension typically gets the callback. If the task takes longer, the system has time to terminate the extension and the app is resumed to handle it. There’s really no way around this. The workaround is to put the code that handles request completion in both your app and your extension (possibly sharing the code via a framework). It would be nice if the extension could disconnect from the session immediately upon starting its request. Alas, that’s not currently possible (r. 18748008). The only way to programmatically disconnect from the session is to invalidate it, and that either cancels all the running tasks (invalidateAndCancel()) or waits for them to complete (finishTasksAndInvalidate()), neither of which is appropriate. One interesting edge case occurs when the app is in the foreground while the share extension comes up. For example, the app might have a share button, from which the user can invoke the share extension. If the share extension starts an URLSession task in that case, it can result in the app’s application(_:handleEventsForBackgroundURLSession:completionHandler:) callback being called while the app is in the foreground. The app doesn’t need to behave differently in this case, but it’s a little unusual. Xcode’s debugger prevents the system from suspending the process being debugged. So, if you run your extension from Xcode, or you attach to its process some time after launch, the process will continue to execute in situations where the system would otherwise have suspended it. This makes it tricky to investigate problems with the ‘extension was suspended before the network request finished’ case. The best way to investigate any issues you encounter is via logging. Note For more information about debugging problems with background networking, see Testing Background Session Code. Keep in mind that not all networking done by your extension has to use a background session. You should use a background session for long-running requests, but if you have short-running requests then it’s best to run them in a standard session. For example, imagine you have a share extension that needs to make two requests: The first request simply gets an upload authorisation token from the server. This request is expected to finish very quickly. The second request actually uploads the file (including the upload authorisation token from the previous request), and is expected to take a long time. It makes sense to only use a background session for the second request. The first request, being short-running, can be done in a standard session, and that will definitely simplify your code. When doing this you have to prevent your extension from suspending while the short-lived request is in flight. You can use ProcessInfo.performExpiringActivity(withReason:using:) for this. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Revision History 2023-08-30 Fixed the formatting. Adopted Swift terminology throughout. Made other minor editorial changes. 2017-04-26 Moved to the new DevForums. Made many editorial changes. Added the section on Xcode’s debugger. Added a section on short-running network requests. 2014-12-05 First posted on the old DevForums.
Posted
by
Post not yet marked as solved
29 Replies
11k Views
I've recently been integrating Background Transfer Service into an application so that the user is able to download files in the background.I did most of my building/testing on an old iPhone 6 device that was running iOS 9.3.5 (I try to keep my previous device back a version of iOS). Background Transfer Service works great on this device. I am able to put 100+ download tasks into the queue and they all finish and report progress as expected after sending the application into the background and then re-opening the application.This also appears to work great on a new 5th generation iPad running iOS 10.3.Where things get weird is on my iPhone 7 Plus which is running iOS 10.3.1. The downloads kick off fine, progress is reported as expected in the didWriteData method, however if I background the application and wait ~10 seconds and re-open the application the progress never catches back up to what progress would have been done in the background and the progress never increments at all (it stays where it was when it was backgrounded). The didFinishDownloading method does end up getting called however it appears to wait until the very end of all the download tasks completions for that method to fire for all of the remaining tasks. So the didWriteData, didFinishDownloading, didCompleteWithError, etc. all happen right at the end in one burst. I have however had a few instances where my iPhone 7 Plus device running iOS 10.3.1 did show progress after bringing the app back into the foreground however those instances I could could on one hand. More often than not (9 times out of 10) the progress is never reported on this device after re-opening the application.I am at a bit of a loss and am wondering if there is a known bug we should be looking out for, and if so when we could expect a fix? Or if there are currently any known work arounds. From my testing/debugging I cannot get progress to work in my application on the iPhone 7 Plus running 10.3.1. I also had a co-worker test this as well and they also experienced this.In fact they went a step further and opened the Netflix application on their 10.3.1 iPhone 7 Plus device and began downloading a movie. Progress incremented as expected, they then backgrounded the application and waited ~20 seconds and re-opened the application, only to find the progress get stuck where it was when the app was initially backgrounded and it never moves. After a given amount of time of the progress not moving the download does eventually finish (the progress indicator disappears) and the Netflix movie is downloaded and able to be played. This is the same behavior I see above in my application.Any help with this would be greatly appreciated.Thanks in advance!Adam
Posted
by
Post not yet marked as solved
14 Replies
5.0k Views
When a batch of download tasks create and resume, some of them are still downloading. Xcode kill the app, and launch app again, then all the tasks failed immediately(if not reproduce, retry these steps). The worst thing is whenever i add new tasks and resume, all of them failed immediately, until i restart the app.I can produce this bug everytime, just follow these tips:NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"***"];NSOperationQueue* operationQueue = [[NSOperationQueue alloc] init];operationQueue.maxConcurrentOperationCount = 1;urlsession = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:operationQueue];for (int i = 0; i < 100; i++){ NSURLSessionDownloadTask* downloadTask = [urlsession downloadTaskWithRequest:urlRequest]; [ downloadTask resume];}Xcode kill the app...Xcode launch app again...The only delegate method be called immediately is:- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)errorError Domain=NSPOSIXErrorDomain Code=2 "No such file or directory" UserInfo={NSErrorFailingURLKey=xx'xx'x'xxxx, NSErrorFailingURLStringKey=***}It's not certain appearing on devices not kill by xcode, but my QA colleagues sometimes got this bug and report to me.Only background session has this bug, defaultSessionConfiguration won't happen.I don't know why "No such file or directory" error is called back, any suggestions?
Posted
by
Post not yet marked as solved
0 Replies
4.1k Views
Questions about FTP crop up from time-to-time here on DevForums. In most cases I write a general “don’t use FTP” response, but I don’t have time to go into all the details. I’ve created this post as a place to collect all of those details, so I can reference them in other threads. IMPORTANT Apple’s official position on FTP is: All our FTP APIs have been deprecated, and you should avoid using deprecated APIs. Apple has been slowly removing FTP support from the user-facing parts of our system. The most recent example of this is that we removed the ftp command-line tool in macOS 10.13. You should avoid the FTP protocol and look to adopt more modern alternatives. The rest of this post is an informational explanation of the overall FTP picture. This post is locked so I can keep it focused. If you have questions or comments, please do create a new thread with the Network tag and I’ll respond there. Don’t Use FTP FTP is a very old and very crufty protocol. Certain things that seem obvious to us now — like being able to create a GUI client that reliably shows a directory listing in a platform-independent manner — are not possible to do in FTP. However, by far the biggest problem with FTP is that it provides no security [1]. Specifically, the FTP protocol: Provides no on-the-wire privacy, so anyone can see the data you transfer Provides no client-authenticates-server authentication, so you have no idea whether you’re talking to the right server Provides no data integrity, allowing an attacker to munge your data in transit Transfers user names and passwords in the clear Using FTP for anonymous downloads may be acceptable (see the note below) but most other uses of FTP are completely inappropriate for the modern Internet. IMPORTANT You should only use FTP for anonymous downloads if you have an independent way to check the integrity of the data you’ve downloaded. For example, if you’re downloading a software update, you could use code signing to check its integrity. If you don’t check the integrity of the data you’ve downloaded, an attacker could substitute a malicious download instead. This would be especially bad in, say, the software update case. These fundamental problems with the FTP protocol mean that it’s not a priority for Apple. This is reflected in the available APIs, which is the subject of the next section. FTP APIs Apple provides two FTP APIs: All Apple platforms provide FTP downloads via NSURLSession Most Apple platforms (everything except watchOS) support CFFTPStream, which allows for directory listings, downloads, uploads, and directory creation. All of these FTP APIs are now deprecated: NSURLSession was deprecated for the purposes of FTP in the 2022 SDKs (macOS 13, {i{,Pad},tv}OS 16, watchOS 9) [2]. CFFTPStream was deprecated in the 2016 SDKs (macOS 10.11, {i{,Pad},tv}OS 9). CFFTPStream still works about as well as it ever did, which is not particularly well. Specifically: There is at least one known crashing bug (r. 35745763), albeit one that occurs quite infrequently. There are clear implementation limitations — like the fact that CFFTPCreateParsedResourceListing assumes a MacRoman text encoding (r. 7420589) — that will not be fixed. If you’re looking for an example of how to use these APIs, check out SimpleFTPSample. Note This sample has not been updated since 2013 and is unlikely to ever be updated given Apple’s position on FTP. The FTP support in NSURLSession has significant limitations: NSURLSession only supports FTP downloads; there is no support for uploads or any other FTP operations NSURLSession does not support resumable FTP downloads [3] NSURLSession background sessions only support HTTP and HTTPS, so you can’t run FTP downloads in the background on iOS If Apple’s FTP APIs are insufficient for your needs, you’ll need to write or acquire your own FTP library. Before you do that, however, consider switching to an alternative protocol. After all, if you’re going to go to the trouble of importing a large FTP library into your code base, you might as well import a library for a better protocol. The next section discusses some options in this space. Alternative Protocols There are numerous better alternatives to FTP: HTTPS is by far the best alternative to FTP, offering good security, good APIs on Apple platforms, good server support, and good network compatibility. Implementing traditional FTP operations over HTTPS can be a bit tricky. One possible way forward is to enable DAV extensions on the server. FTPS is FTP over TLS (aka SSL). While FTPS adds security to the protocol, which is very important, it still inherits many of FTP’s other problems. Personally I try to avoid this protocol. SFTP is a file transfer protocol that’s completely unrelated to FTP. It runs over SSH, making it a great alternative in many of the ad hoc setups that traditionally use FTP. Apple does not have an API for either FTPS or SFTP, although on macOS you may be able to make some headway by invoking the sftp command-line tool. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] In another thread someone asked me about FTP’s other problems, those not related to security, so let’s talk about that. One of FTP’s implicit design goals was to provide cross-platform support that exposes the target platform. You can think of FTP as being kinda like telnet. When you telnet from Unix to VMS, it doesn’t aim to abstract away VMS commands, so that you can type Unix commands at the VMS prompt. Rather, you’re expected to run VMS commands. FTP is (a bit) like that. This choice made sense back when the FTP protocol was invented. Folks were expecting to use FTP via a command-line client, so there was a human in the loop. If they ran a command and it produced VMS-like output, that was fine because they knew that they were FTPing into a VMS machine. However, most users today are using GUI clients, and this design choice makes it very hard to create a general GUI client for FTP. Let’s consider the simple problem of getting the contents of a directory. When you send an FTP LIST command, the server would historically run the platform native directory list command and pipe the results back to you. To create a GUI client you have to parse that data to extract the file names. Doing that is a serious challenge. Indeed, just the first step, working out the text encoding, is a challenge. Many FTP servers use UTF-8, but some use ISO-Latin-1, some use other standard encodings, some use Windows code pages, and so on. I say “historically” above because there have been various efforts to standardise this stuff, both in the RFCs and in individual server implementations. However, if you’re building a general client you can’t rely on these efforts. After all, the reason why folks continue to use FTP is because of it widespread support. [2] To quote the macOS 13 Ventura Release Notes: FTP is deprecated for URLSession and related APIs. Please adopt modern secure networking protocols such as HTTPS. (92623659) [3] Although you can implement resumable downloads using the lower-level CFFTPStream API, courtesy of the kCFStreamPropertyFTPFileTransferOffset property. Revision History 2024-04-15 Added a footnote about FTP’s other problems. Made other minor editorial changes. 2022-08-09 Noted that the FTP support in NSURLSession is now deprecated. Made other minor editorial changes. 2021-04-06 Fixed the formatting. Fixed some links. 2018-02-23 First posted.
Posted
by
Post marked as solved
15 Replies
11k Views
I read here that when using `URLSessionConfiguration.background(withIdentifier:)`, it shouldn't timeout and should try again 'till there is an available internet connection or 'till `timeoutIntervalForResource` reached out (which is set to 7 days), but in this case, I'm getting the timeout after less than 15 seconds and after that it doesn't seems to try again, also when there is an internet connection (e.g. turning off Network Link Conditioner).I haven't set anything to that time so I really don't know why this is happening, all I've done is to set `100% Loss` in Network Link Conditioner to check offline usage (which shouldn’t matter to URLSession since it using background configuration).In short:My goal is to start the session whenever there is or there isn't an internet connection and let it fetch as soon as it can, when there is an available internet connection.What happens right now is that the session is timed out and not performing the session also when there is an internet connection (e.g. turning off Network Link Conditioner).*It's important to note that when there is an available internet connection while the session is resumed, it does fetching successfully, so the issue is not with the server I'm sending the task to for sure.Here is my code:Defining session configuration:static let urlSessionConfiguration: URLSessionConfiguration = { let configuration = URLSessionConfiguration.background(withIdentifier: FilesManager.urlSessionIdentifier) configuration.sessionSendsLaunchEvents = false configuration.sharedContainerIdentifier = "myApp" return configuration }()Starting the session:let url = URL(string: "https://url.com/path")! var urlRequest = URLRequest(url: url) urlRequest.httpMethod = "POST" urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") urlRequest.httpBody = body URLSession(configuration: FilesManager.urlSessionConfiguration, delegate: self, delegateQueue: nil).dataTask(with: urlRequest).resume()Delegate:extension FilesManager: URLSessionDataDelegate, URLSessionDelegate { func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { print("\(#function) \(error)") } }Print in console:urlSession(_:task:didCompleteWithError:) Optional(Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={_kCFStreamErrorCodeKey=-2104, _NSURLErrorFailingURLSessionTaskErrorKey=BackgroundDataTask .<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=( "BackgroundDataTask .<1>", "LocalDataTask .<1>" ), NSLocalizedDescription=The request timed out., _kCFStreamErrorDomainKey=4, NSErrorFailingURLStringKey=https://url.com/path, NSErrorFailingURLKey=https://url.com/path})If you know a better way to achieve my goal or you’re think there is something wrong in this code, please, let me know.Thanks,Ido.
Posted
by
Post not yet marked as solved
2 Replies
3.7k Views
Hi,I'm wondering would the network request be successful if a 302 redirect is placed on the server and the app doesn't explicitly implement 'willPerformHTTPRedirection' delegate?We are working on domain migrations and are concerned about backward compatibility of apps to make successful requests(200) when the url redirects are effective.Appreciate the help.
Posted
by
Post not yet marked as solved
26 Replies
9.1k Views
Hi, I am facing a strange issue in my app with iOS14 there is a intermittent crash, i am using NetServiceBrowser for MDNS discovery not sure if that is causing the problem crash log has below information: Crashed: com.apple.main-thread 0 CoreFoundation 0x1a906c4c4 CFAssertMismatchedTypeID + 108 1 CoreFoundation 0x1a8f7db0c CFRunLoopSourceRemoveFromRunLoop + 298 2 CFNetwork 0x1a96255b0 CFNetServiceBrowserStopSearch + 460 3 CoreFoundation 0x1a8f81240 CFRUNLOOPISCALLINGOUTTOASOURCE0PERFORMFUNCTION + 24 4 CoreFoundation 0x1a8f81140 CFRunLoopDoSource0 + 204 5 CoreFoundation 0x1a8f80488 CFRunLoopDoSources0 + 256 6 CoreFoundation 0x1a8f7aa40 CFRunLoopRun + 776 7 CoreFoundation 0x1a8f7a200 CFRunLoopRunSpecific + 572 8 GraphicsServices 0x1bf075598 GSEventRunModal + 160 9 UIKitCore 0x1ab840004 -[UIApplication run] + 1052 10 UIKitCore 0x1ab8455d8 UIApplicationMain + 164
Posted
by
Post not yet marked as solved
0 Replies
14k Views
I regularly get asked questions about local network privacy. This is my attempt to collect together the answers for the benefit of all. Before you delve into the details, familiarise yourself with the basics by watching WWDC 2020 Session 10110 Support local network privacy in your app. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Local Network Privacy FAQ With local network privacy, any app that wants to interact with devices on your network must ask for permission the first time that it attempts that access. Local network privacy is implemented on iOS, iPadOS, and the current visionOS beta. It’s not implemented on other platforms, including macOS and tvOS. Some common questions about local network privacy are: FAQ-1 What is a local network? FAQ-2 What operations require local network access? FAQ-3 What operations require the multicast entitlement? FAQ-4 Do I need the multicast entitlement? FAQ-5 I’ve been granted the multicast entitlement; how do I enable it? FAQ-6 Can App Clips access the local network? FAQ-7 How does local network privacy work with app extensions? FAQ-8 How do I explicitly trigger the local network privacy alert? FAQ-9 How do I tell whether I’ve been granted local network access? FAQ-10 How do I use the unsatisfied reason property? FAQ-11 Do I need a local network usage description property? FAQ-12 Can I test on the simulator? FAQ-13 Once my app has displayed the local network privacy alert, how can I reset its state so that it shows again? FAQ-14 How do I map my Multipeer Connectivity service type to an entry in the Bonjour services property? FAQ-15 My app presents the local network privacy alert unexpectedly. Is there a way to track down the cause? FAQ-16 On a small fraction of devices my app fails to present the local network privacy alert. What’s going on? FAQ-17 Why does local network privacy get confused when I install two variants of my app? FAQ-18 Can my app trigger the local network privacy alert when the device is on WWAN? Revision History 2023-10-31 Fixed a bug in the top-level FAQ that mistakenly removed some recent changes. Added FAQ-18. 2023-10-19 Added a preamble to clarify that local network privacy is only relevant on specific platforms. 2023-09-14 Added FAQ-17. 2023-08-29 Added FAQ-16. 2023-03-13 Added connecting a UDP socket to FAQ-2. 2022-10-04 Added screen shots to FAQ-11. 2022-09-22 Fixed the pointer from FAQ-9 to FAQ-10. 2022-09-19 Updated FAQ-3 to cover iOS 16 changes. Made other minor editorial changes. 2020-11-12 Made a minor tweak to FAQ-9. 2020-10-17 Added FAQ-15. Added a second suggestion to FAQ-13. 2020-10-16 First posted.
Posted
by
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
Post not yet marked as solved
2 Replies
1.3k Views
My device is Apple Watch Series 5. It only support wifi. When I was debug in real machine. It can't connect to internet. The app is independent. But the system app can connect to internet. Why? Why? Why? And How to solve. code : let session = URLSession.shared     let task: URLSessionDataTask = session.dataTask(with: URLRequest(url: URL(string: "https://www.baidu.com/s?wd=iOS")!)) { [self] (data, response, error) in       if data == nil {                   print(error.debugDescription)       }     }     task.resume() error message : Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={_NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <FD086BDC-3051-469F-9280-0054CC8F0488>.<1>, NSLocalizedDescription=The Internet connection appears to be offline., _kCFStreamErrorCodeKey=50, _NSURLErrorRelatedURLSessionTaskErrorKey=(   "LocalDataTask <FD086BDC-3051-469F-9280-0054CC8F0488>.<1>",   "LocalDataPDTask <FD086BDC-3051-469F-9280-0054CC8F0488>.<1>",   "LocalDataTask <FD086BDC-3051-469F-9280-0054CC8F0488>.<1>" ), NSErrorFailingURLStringKey=https://www.baidu.com/s?wd=iOS, _kCFStreamErrorDomainKey=1, NSErrorFailingURLKey=https://www.baidu.com/s?wd=iOS})
Posted
by
Post not yet marked as solved
2 Replies
2.3k Views
Hi, I'm developing an independent WatchOS application, and trying to use background URL sessions to download new content for complication update. I think my download tasks are scheduled up appropriately, during a background refresh, following all documented guidelines from apple documentation. Everything seems to work as intended on the simulator. But when running on the real device (from XCode, using a self-signed certificate), the updates become quite unreliable (and the debug process is very frustrating btw). Most of the times, the scheduled download never finishes until the app returns to foreground. And I get the following error in the logs : BackgroundSession ... connection to background transfer daemon [interrupted | invalidated] I read that this might be due to a code signing issue. Does it mean that I have to register to an apple developer account to get it working on the real device ? (Needless to say that I'm not naturally inclined to subscribe while I'm not sure to get the app running as intended...) Thanks a lot for any help
Posted
by
Post not yet marked as solved
3 Replies
917 Views
Hello, For our iOS app, we're switching WebSocket client implementation from one using Poco project - https://github.com/pocoproject/poco to one based on NSURLSessionWebSocketTask. We are observing one regression which prevents us from shipping this solution though: 5-7% of calls to -[NSURLSessionWebSocketTask cancelWithCloseCode:reason:] fail to deliver given close code to server and 1006 close code (AbnormalClosure) is used instead. Our test consist of following steps: Create WebSocket using NSURLSessionWebSocketTask Send "Hello" message Close WebSocket with 1011 close code Destroy NSURLSessionWebSocketTask instance Check whether server received 1011 close code We do not perform those steps line by line, but rather use delays (~100-200ms) between each step. We perform such test 1000 times and observe 5-7% failure rate consistently. Distribution of failures is random. We did perform test on both iOS simulator and iOS devices with no observable differences. We did perform test on multiple server implementations (tornado- and node.js based ones) running on local machine (same as Xcode) and remote one We always receive "Hello" message on server 1011 close code is arbitrarily chosen for testing, but results are same for different ones, too. We did setup mitmproxy and for failed tests see following log: Error in WebSocket connection to 20.16.12.131:8080: WebSocket connection closed unexpectedly by client: TcpDisconnect(None) We did enable CFNetwork diagnostic using CFNETWORK_DIAGNOSTICS and found one difference between success and failure cases. For successful cases we see log which looks like this: default 16:27:15.831193+0200 Playground-ObjC tcp_close [C7.1:2] TCP Packets: snd 0.000s seq 1092086878:1092086879 ack 0 win 65535 len 0 [SEC] rcv 0.004s seq 3101059099:3101059100 ack 1092086879 win 65535 len 0 [S.] snd 0.000s seq 1092086879:1092086879 ack 3101059100 win 4117 len 0 [.] snd 0.002s seq 1092086879:1092087279 ack 3101059100 win 4117 len 400 [P.] rcv 0.001s seq 3101059100:3101059100 ack 1092086879 win 2058 len 0 [.] rcv 0.000s seq 3101059100:3101059100 ack 1092087279 win 2052 len 0 [.] rcv 0.015s seq 3101059100:3101059229 ack 1092087279 win 2052 len 129 [P.] ECT0 snd 0.000s seq 1092087279:1092087279 ack 3101059229 win 4113 len 0 [.] snd 0.003s seq 1092087279:1092087289 ack 3101059229 win 4113 len 10 [P.] rcv 0.002s seq 3101059229:3101059229 ack 1092087289 win 2052 len 0 [.] snd 0.017s seq 1092087289:1092087297 ack 3101059229 win 4113 len 8 [P.] snd 0.001s seq 1092087297:1092087298 ack 3101059229 win 4113 len 0 [F.] rcv 0.000s seq 3101059229:3101059229 ack 1092087297 win 2052 len 0 [.] rcv 0.001s seq 3101059229:3101059233 ack 1092087297 win 2052 len 4 [P.] ECT0 Last packet 0ms ago. So it's something related to "tcp_close" and seems to log whole TCP packets that were exchanged during connection. For failed cases such log is not present. One additional log we see potentially interesting (but were not able to confirm its meaning or relation to failed cases) comes from runningboardd: default 16:27:15.830447+0200 runningboardd Invalidating assertion 33-1364-23682 (target:[applicationorg.example.app:1364]) from originator [applicationorg.example.app:1364] So that's where we are right now and we have no idea where to dig next. We wonder if anyone else have seen such problem or can point us to any direction we could try next. Thanks much, Damian & Maciek
Posted
by
Post not yet marked as solved
8 Replies
2.4k Views
I am working on an application where there is a need to do a specific API only through Mobile Data and not wifi, allowing other API calls to be done using the available network type whether cellular data or wifi or .... Is there a way to force use Mobile data usage even if WIFI is ON on this API call.
Posted
by
Post marked as solved
5 Replies
1.8k Views
I have a working background URLSession. I know that upon creating an URLSession with the same session identifier I get a "background URLSession with identifier x already exists" message. I know that I can store the session and call .finishTasksAndInvalidate() on it if needed. My use case is that if the application terminates, and the user relaunches the application before the background task completes, I need to be able to check if a background URLSession with the same identifier exists, and if it does, restitute the application state with the same handlers (so that I can update a UIProgressView for example). I have two questions: How do I check that a background URLSession with a given identifier already exists? Does the AppDelegate completion handler still get called if the application was terminated and relaunched?
Posted
by
Post not yet marked as solved
9 Replies
3.8k Views
I have received two strange crash reports from an iPad11,7 running iPadOS 15.1 and an iPad11,2 running iPadOS 15.2. On both occasions, the crashed thread calls CFURLRequestSetMainDocumentURL, which in turn calls _dispatch_source_set_runloop_timer_4CF in libdispatch, after which the application crashes with SIGSEGV and SEGV_MAPERR. The crashed thread's call stack is displayed below. Full crash logs are attached as well. What could this be? Exception Type: SIGSEGV Exception Codes: SEGV_MAPERR at 0x21d Crashed Thread: 20 Thread 20 Crashed: 0 libdispatch.dylib 0x00000001829e1784 _dispatch_source_set_runloop_timer_4CF + 36 1 CFNetwork 0x00000001834fc824 CFURLRequestSetMainDocumentURL + 2240 2 CFNetwork 0x00000001836b89a8 _CFNetworkErrorGetLocalizedDescription + 693652 3 CFNetwork 0x00000001834fdb1c CFURLRequestSetMainDocumentURL + 7096 4 CFNetwork 0x00000001834f3c34 CFURLRequestSetURL + 9668 5 libdispatch.dylib 0x00000001829ca914 _dispatch_call_block_and_release + 28 6 libdispatch.dylib 0x00000001829cc660 _dispatch_client_callout + 16 7 libdispatch.dylib 0x00000001829d3de4 _dispatch_lane_serial_drain + 668 8 libdispatch.dylib 0x00000001829d498c _dispatch_lane_invoke + 440 9 libdispatch.dylib 0x00000001829d5c74 _dispatch_workloop_invoke + 1792 10 libdispatch.dylib 0x00000001829df1a8 _dispatch_workloop_worker_thread + 652 11 libsystem_pthread.dylib 0x00000001f1eea0f4 _pthread_wqthread + 284 12 libsystem_pthread.dylib 0x00000001f1ee9e94 start_wqthread + 4 second_crashlog.txt report-2517628380750009999-e4d7ea06-6f22-4b7e-b129-045599e1dee5.txt
Posted
by
Post not yet marked as solved
6 Replies
3.3k Views
We have been seeing a NSURLError cannot parse error with error code -1017 for 0.01% of all the requests fired from our native app. We double checked the request headers and cookies but found no difference from the API calls that succeeded for the same path. For most of these requests, we found (through our analytics tools) that 99% of the times, there was no response received from the server(response object is nil); trying to understand why would a no response cause a cannot parse error. We do not get much information from error received as to what really went wrong, did the request even reach the server or was killed or modified by the OS? Any help or further detail will be very helpful. Error in detail: Foundation.URLError(_nsError: Error Domain=NSURLErrorDomain Code=-1017 "cannot parse response" UserInfo={NSUnderlyingError=0x280eddc50 {Error Domain=kCFErrorDomainCFNetwork Code=-1017 "(null)" UserInfo={_kCFStreamErrorCodeKey=-1, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=https://mydomain.com/path, NSErrorFailingURLKey=https://mydomain.com/path, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-1, NSLocalizedDescription=cannot parse response})
Posted
by
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