iOS API调用偶现'data parameter is nil'异常求助
Hey Renee, let's break down your problem step by step—you're hitting two main issues here: the TCP error code 53 that pops up when returning from the background, and the fatal crash caused by trying to parse nil data. Let's fix them one by one:
First, Stop the Immediate Crash
The crash happens because you’re calling NSJSONSerialization JSONObjectWithData:data without checking if data is nil or if an error occurred. When the TCP connection fails (error 53), the data parameter will be nil, and trying to parse it throws that NSInvalidArgumentException.
Add a guard check right at the start of your completion handler to handle this:
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler: ^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { // First handle errors and nil data if (error != nil || data == nil) { NSLog(@"API Request Failed: %@", error?.localizedDescription ?: @"No data received"); dispatch_async(dispatch_get_main_queue(), ^{ [self->HUD hide:YES]; // Optionally show an alert to the user about the network issue }); return; } // Now proceed with JSON parsing, and check for parsing errors too NSError *jsonError = nil; NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonError]; if (jsonError != nil) { NSLog(@"JSON Parsing Failed: %@", jsonError.localizedDescription); dispatch_async(dispatch_get_main_queue(), ^{ [self->HUD hide:YES]; }); return; } // Rest of your parsing logic for arrList, arrActive, etc. }] resume];
Fix the TCP Error 53 (Connection Failure on Background → Foreground Switch)
Error code 53 in iOS usually means the TCP connection was reset—this often happens when your app is in the background and the system drops idle connections, or the network state changed (like switching from Wi-Fi to cellular).
Here’s how to mitigate this:
- Check network state first: Use
NWPathMonitor(from the Network framework) to verify if the device has an active network connection before firing the API call. This prevents trying to make requests when there’s no network. - Implement retry logic: When you get error 53, add a limited retry mechanism (2-3 retries max) to reattempt the request.
- Use a custom URLSession: The shared
NSURLSessionhas default settings that don’t handle background transitions well. Create a custom session withwaitsForConnectivity = YESto let it wait for a network connection instead of failing immediately:NSURLSessionConfiguration *config = NSURLSessionConfiguration.defaultConfiguration; config.waitsForConnectivity = YES; NSURLSession *customSession = [NSURLSession sessionWithConfiguration:config]; // Use customSession for your data tasks instead of sharedSession
Fix the URL Formatting Bug (Critical!)
Looking at your code, there’s a major issue with how you’re building targetUrl:
targetUrl = [NSString stringWithFormat:@"https://yoururl",[dict valueForKey:@"support_location"],@"1000"];
You’re using stringWithFormat but your format string has no placeholders (%@) for the two parameters you’re passing. This means your URL is just https://yoururl (likely invalid) instead of including the support_location and limit. Fix this by adding the missing placeholders:
// Adjust the format to match your actual API endpoint structure targetUrl = [NSString stringWithFormat:@"https://yoururl/%@?limit=%@",[dict valueForKey:@"support_location"],@"1000"];
This is probably a key reason some requests fail—invalid URLs will trigger connection errors.
Other Code Improvements
- Avoid
self->for instance variables: Use property accessors (likeself.arrListinstead ofself->arrList) to ensure proper memory management and KVO compliance. - Null-check dictionary values: When accessing keys like
user_id, verify the value isn’t nil before converting to an integer (e.g.,[dict valueForKey:@"user_id"] ?: @0). - Reuse your URLSession: Create your custom session once (in
viewDidLoador init) instead of recreating it every time you make a request.
With these changes, your API calls will handle network failures gracefully, avoid crashes, and be much more stable—especially when switching between background and foreground.
内容的提问来源于stack exchange,提问作者Renee

