In iOS 10.2, we fix this error when we try to communicate with several different apis. The strangest thing is that we sometimes encounter this in ~ 2 out of 200 requests for the same URL. But on the other hand, sometimes I can make 3000 api calls without seeing a problem.
As far as I read, this is related to ATS. The result also shows us that we are getting an error code that relates to ATS: kCFStreamErrorCodeKey = -9806.
However, I do not understand how this can relate to ATS, due to a few points:
- The url I'm calling is https.
- The server has a valid TLSv1.2 certificate
- I tried to throw an exception but it does nothing
We tried to create an exception in different ways, both by resolving severe loads, and created an exception for the domain.
Although this is not necessary if the server has a valid certificate, we tried to throw an exception
So we created an exception for the domain.
<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>deezer.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> <true/> <key>NSTemporaryExceptionMinimumTLSVersion</key> <string>TLSv1.2</string> <key>NSTemporaryExceptionRequiresForwardSecrecy</key> <false/> </dict> </dict> </dict>
And thatβs how we included the arbitration loads:
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
Another oddity is that we only use this on iOS 10 (10.2). When we test in iOS 9.3, everything works as expected.
I made an example application to reproduce this.
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self Perform]; } int i = 0; - (void) Perform { NSURLSessionConfiguration *defaultConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *sessionWithoutADelegate = [NSURLSession sessionWithConfiguration:defaultConfiguration]; NSURL *url = [NSURL URLWithString:(@"https://api.deezer.com/chart/0/tracks")]; [[sessionWithoutADelegate dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if(error != NULL) { NSLog(@"Got response with error %@.\n", error); } NSLog(@"%d",i); i++; if(i <1000) { [self Perform]; } }] resume]; }
Does anyone have any ideas for solutions? Thanks