【问题标题】:NSURLSessionTask category method crashes with "Unrecognized selector sent to instance"NSURLSessionTask 类别方法因“无法识别的选择器发送到实例”而崩溃
【发布时间】:2017-05-17 12:30:39
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • 感谢您的指点,我会尝试您的建议。顺便说一句,您认为文档中某处提到了这个问题吗?
    • 不,我仍然不明白这是一个错误还是一个“功能”
    【解决方案2】:

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

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

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      我相信我知道这种相当奇怪(至少对我而言)行为的根源是什么。我将提供一个我在 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;
      

      丑吗?是的!但它现在有效。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-24
        • 1970-01-01
        • 1970-01-01
        • 2014-08-25
        • 2015-08-02
        • 1970-01-01
        相关资源
        最近更新 更多