NSURLConnection迁移至NSURLSession后代理未触发问题求助
解决NSURLSession代理方法未被调用的问题
看起来你在把NSURLConnection迁移到NSURLSession时遇到了代理方法不触发的问题,我帮你梳理下代码里的几个关键错误,改完这些应该就能解决了:
1. 确保NSURLSession被强持有且正确初始化代理
NSURLSession如果是局部变量会被立即释放,而且必须显式指定delegate才能触发代理回调。首先给你的类添加一个强引用的session属性:
@property (strong, nonatomic) NSURLSession *session;
然后修改createSession方法,必须配置delegate和delegateQueue:
- (void)createSession { if (!self.session) { NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; // 指定当前类为代理,同时设置回调队列(这里用主队列和你原来的NSURLConnection行为一致) self.session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]]; } }
注意:不要用
[NSURLSession sharedSession],这个默认session不会触发代理方法。
2. 修复didReceiveResponse代理方法,必须调用completionHandler
你当前的实现没有调用传入的completionHandler,这会让NSURLSession不知道如何处理后续响应,直接导致didReceiveData等后续代理方法不触发。修改后:
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler { // 建议把receivedData改成类的属性,避免全局变量的问题 self.receivedData = [[NSMutableData alloc] init]; // 必须调用这个block,告诉session允许继续接收数据 completionHandler(NSURLSessionResponseAllow); }
3. 修复认证挑战代理方法,改用NSURLSession的completionHandler处理
你还在沿用NSURLConnection的challenge.sender方式处理认证,这在NSURLSession里是无效的,必须用传入的completionHandler来完成挑战处理:
-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { NSURLCredential *cred = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; // 通过completionHandler告诉session使用这个凭证 completionHandler(NSURLSessionAuthChallengeUseCredential, cred); } else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]) { // 无客户端证书时继续请求 completionHandler(NSURLSessionAuthChallengeContinueWithoutCredential, nil); } else { // 其他认证类型默认处理,避免请求卡住 completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); } }
4. 修复willCacheResponse代理方法,正确调用completionHandler
当前实现没有调用completionHandler,这会导致缓存逻辑异常,需要通过block返回nil来禁用缓存:
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask willCacheResponse:(NSCachedURLResponse *)proposedResponse completionHandler:(void (^)(NSCachedURLResponse * _Nullable))completionHandler { // 传入nil禁用缓存,和你原来的NSURLConnection行为一致 completionHandler(nil); }
5. 优化receivedData的使用(可选但推荐)
把全局的receivedData改成类的属性,避免多线程下的问题,同时更符合OC的编码规范:
@property (strong, nonatomic) NSMutableData *receivedData;
后续所有操作都用self.receivedData来替代全局变量。
把这些修改都完成后,你的NSURLSession代理方法应该就能正常触发了,功能也会和原来的NSURLConnection保持一致。
内容的提问来源于stack exchange,提问作者Francis F
相关产品推荐
相关产品推荐

