NSURLSessionTask类别方法崩溃,“无法识别的选择器发送到实例”

时间:2014-06-27 09:53:06

标签: ios objective-c objective-c-category

我需要向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

3 个答案:

答案 0 :(得分:5)

不幸的是,NSURLSession似乎不支持类别。我遇到了一个像尝试添加关联对象的问题。
另请参阅here

答案 1 :(得分:4)

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

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

希望这有帮助。

答案 2 :(得分:1)

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

当您尝试使用已在类别-myMethod中添加的方法时,您会看到如下异常:

  

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

我开始挖掘并发现在运行时隐藏在 NSURLSessionDataTask 类后面的 __ NSCFLocalDataTask 类只是转换为 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;

丑?是!但它现在有效。