NSURLSessionTask category 方法崩溃并"Unrecognized selector sent to instance"



我需要为NSURLSessionTask添加方法。这是我的类别,它应该这样做:

//  NSURLSessionTask+Extras.h
#import <Foundation/Foundation.h>
@interface NSURLSessionTask (Extras)
- (void)helloNSURLSessionTask;
@end
//  NSURLSessionTask+Extras.m
#import "NSURLSessionTask+Extras.h"
@implementation NSURLSessionTask (Extras)
- (void)helloNSURLSessionTask {
    NSLog(@"hello NSURLSessionTask!");
}
@end

一切都很好,自动完成工作,但当我调用这个方法时,我的应用程序崩溃了:

2014-06-27 12:32:23.916 Test[4333:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFLocalDataTask helloNSURLSessionTask]: unrecognized selector sent to instance 0x109723310'

如果我将类别添加到NSObject,同样的方法也可以工作,我似乎无法理解为什么它不适合NSURLSessionTask

下面是一个为我再现这个问题的测试项目:https://dl.dropboxusercontent.com/u/25100182/Test.zip

不幸的是,NSURLSession似乎不支持类别。我在尝试添加关联对象时遇到过类似的问题。

我在NSURLSessionDataTask类别中有类似的问题,当我将范围缩小到NSURLSessionTask时,它似乎工作正常。

@interface NSURLSessionTask (iRemoteWallet)
    @property (nonatomic, weak) id context;
@end

我相信我知道这种相当奇怪的(至少对我来说)行为的起源。我将提供一个我在iOS 9.2中遇到的NSURLSessionDataTask的例子。

当你尝试使用你在类别-myMethod:中添加的方法时,你会看到这样的异常:

[__NSCFLocalDataTask -myMethod]:无法识别的选择器发送到实例

我已经开始挖掘,发现__NSCFLocalDataTask类隐藏在我们的NSURLSessionDataTask类在运行时只是被转换为NSURLSessionDataTask,但不继承它。这个类继承链是__NSCFLocalDataTask: __NSCFLocalSessionTask: __NSCFURLSessionTask: NSObject。所以我的分类根本不适用于这门课。难怪没人认出来。

一个解决方案可能是将你的类别移到NSObject并做一堆检查。我是这样做的:
if ([self respondsToSelector:@selector(response)]) {
    id response = [self performSelector:@selector(response)];
    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
        return [NSString stringWithFormat:@"%td", ((NSHTTPURLResponse *)response).statusCode];
    }
}
NSException *e =[NSException exceptionWithName:NSInternalInconsistencyException reason:@"errorCode: method should be only used on classes that implement -(NSHTTPURLResponse *)response: method." userInfo:nil];
@throw e;

丑吗?是的!

相关内容

最新更新