You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NSURLSession调用后端API出现-999/-1200错误,已配置ATS仍未解决

Troubleshooting NSURLSession Errors (-999 & -1200) Even After ATS Configuration

Hey there, let's dig into these frustrating intermittent errors you're seeing with NSURLSession. I've dealt with both -999 and -1200 plenty of times, so let's break down what they mean and what might still be off even after you've set up ATS.

First, Let's Decode the Error Codes

These codes aren't just random numbers—they tell us exactly what's going wrong:

  • Error -999: This is almost always a request cancellation. It can happen if you fire off duplicate requests, the session gets invalidated early, or your code explicitly cancels the task before it finishes.
  • Error -1200: This is an SSL/TLS validation failure tied to ATS. Even if you think you've configured ATS correctly, there are often edge cases that slip through.

Step-by-Step Troubleshooting

1. Double-Check Your ATS Configuration in info.plist

It's easy to misconfigure ATS—let's verify these details:

  • If you're using NSAllowsArbitraryLoads, make sure it's set to YES under the NSAppTransportSecurity dictionary. Note that on iOS 10+, this setting is ignored if you've specified NSExceptionDomains (domain-specific exceptions take priority).
  • For domain-specific exceptions (NSExceptionDomains):
    • Ensure NSIncludesSubdomains is set to YES if your API uses subdomains (e.g., api.yourdomain.com).
    • Check that NSExceptionAllowsInsecureHTTPLoads (if you need HTTP) or NSExceptionRequiresForwardSecrecy (adjust if your backend doesn't support TLS 1.2+) are set correctly.
  • Confirm there are no typos in your domain names—even a single wrong character can break ATS exceptions.

2. Fixing Error -999 (Request Cancellation)

  • Check for duplicate requests: If users can trigger the API call multiple times quickly (e.g., double-tapping a button), the first request gets cancelled when the second one fires. Add logic to disable the button while the request is in flight, or cancel the existing request before starting a new one intentionally.
  • Verify session lifecycle: If your NSURLSession instance is a local variable (not a property), ARC might release it before the request completes, which cancels the task. Declare your session as a strong property in your class to keep it alive:
    // In your .h or class extension
    @property (strong, nonatomic) NSURLSession *apiSession;
    
    // In your .m
    self.apiSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
    
  • Look for accidental cancels: Search your code for cancel calls on NSURLSessionTask—you might have logic that cancels tasks under conditions you didn't account for.

3. Resolving Error -1200 (SSL/TLS Issues)

  • Inspect the SSL handshake: Use Xcode's Network Inspector (Window > Show Network Inspector) to watch the request flow. Look for SSL errors in the timeline—this will tell you if the certificate is invalid, expired, or doesn't match the domain.
  • Validate your backend's SSL certificate: Run this command in Terminal to check the certificate chain:
    openssl s_client -connect your-api-domain.com:443
    
    Look for errors like "unable to get local issuer certificate"—this means your backend's certificate isn't trusted by iOS's default root store.
  • Handle self-signed certificates: If you're using a self-signed cert for testing, ATS settings alone aren't enough. You need to implement the delegate method to trust the certificate:
    - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
            NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
        } else {
            completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
        }
    }
    
    Note: Only do this for testing—never ship this to production unless you have a secure way to validate the cert.

4. Code Optimization Tips

Add better error logging and session configuration to catch issues earlier:

// Configure your session with timeouts and connection limits
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.timeoutIntervalForRequest = 30; // 30-second timeout for each request
config.timeoutIntervalForResource = 60; // 60-second total timeout for the resource
config.httpMaximumConnectionsPerHost = 5; // Limit concurrent connections to your API

NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];

// Enhanced error logging in the delegate method
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    if (error) {
        NSLog(@"Request failed: %@", error.localizedDescription);
        NSLog(@"Error code: %ld, Domain: %@", (long)error.code, error.domain);
        NSLog(@"Full error details: %@", error.userInfo);
        // The userInfo dictionary often has extra context like SSL certificate info
    }
}

Final Notes

Intermittent errors can be tricky—try to reproduce the issue consistently (e.g., on a specific network, or after certain user actions) to narrow down the cause. If you're still stuck, sharing the full info.plist ATS snippet and more details about your backend's SSL setup would help pinpoint the problem.

内容的提问来源于stack exchange,提问作者Awesome.Apple

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:13:22