Hey guys,
since NSURLConnection is deprecated in iOS 9, I'm trying to replace it with the recommended NSURLSession. When the completion handler of my NSURLSessionDataTask is getting called my app terminates due to an uncaught exception 'NSInvalidArgumentException' – the reason: 'data parameter is nil'. Of course a corrupt URL can be the reason for this error, but I've already checked that. Now, let me show you my code:
- (void)downloadItemsWithQuery:(NSString *)searchString {
NSString *theQuery = [searchString uppercaseString];
NSString *encodedString = [theQuery stringByAddingPercentEncodingWithAllowedCharacters:
[NSCharacterSet characterSetWithCharactersInString:@"!*'();:@&=+$,/?%#[]"]];
NSURL *theURL = [NSURL URLWithString:[NSString stringWithFormat:
@"http://alexpoets.com/VPlan/service.php?klasse=%@", encodedString]];
NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithURL:theURL
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
_downloadedData = [[NSMutableData alloc] init];
[_downloadedData appendData:data];
}];
[dataTask resume];
I tried to debug the app – the app terminates in line 09. Does anyone of you have a clue why the data parameter is nil? I really appreciate any help you can provide.
Best wishes,
Alex
Looking at that code, I would suspect the "data is nil" error is coming from some other place, not from your NSURLSession completion block. If you are positive that's where the crash is, then if error is nil and data is nil, there must be an error HTTP response. Perhaps you're using the iOS 9 SDK and are getting tripped up by App Tranport Security. I do think you need to code more defensively there (check if data is nil, and check the HTTP response code).
Anyway here's one big thing that won't work with that code: NSURLSession is an asynchronous API. The completion block has not yet been called (most likely the request hasn't even gone out) by the time you hit that code that's attempting to parse the result. It's like you asked your roommate to go to the store and get some beer and put it in the fridge, then immediately went to the fridge and tried to pour out a beer. It's just not there yet. You need to defer all that parsing stuff until after the result comes in (i.e. put it in a separate method and call it from your completion block).