Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSURLSessionTask category method crashes with "Unrecognized selector sent to instance"

I need to add method to NSURLSessionTask. Here's my category which is supposed to do that:

//  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

Everything compiles well, autocomplete works, but when I call this method, my application crashes:

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'

Same approach works if I add category to NSObject, and I can't seem to understand why it doesn't for NSURLSessionTask.

Here's a test project which reproduces this problem for me: https://dl.dropboxusercontent.com/u/25100182/Test.zip

like image 725
Andrii Chernenko Avatar asked Jun 27 '14 09:06

Andrii Chernenko


3 Answers

Unfortunately it doesn't seem that NSURLSession can support categories. I've run into a problem like that trying to add an associated object.
See also here.

like image 118
Andrea Avatar answered Nov 05 '22 17:11

Andrea


I had similar issue at NSURLSessionDataTask category, when I reduced the scope to NSURLSessionTask it seems to be working correctly.

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

Hope this helps.

like image 4
Ramesh Avatar answered Nov 05 '22 16:11

Ramesh


I believe I know what is the origin of this rather odd (to me at least) behaviour. I will provide an example that I've encountered with NSURLSessionDataTask in iOS 9.2.

When you try to use the method that you've added in a category -myMethod: you will see an exception like this:

[__NSCFLocalDataTask -myMethod]: unrecognised selector sent to instance

I've started digging and discovered that __NSCFLocalDataTask class that hides behind our NSURLSessionDataTask class at runtime is just casted to NSURLSessionDataTask but does not inherit from it. This class inheritance chain is __NSCFLocalDataTask : __NSCFLocalSessionTask : __NSCFURLSessionTask : NSObject. So my category does not apply to this class at all. No wonder it is unrecognised.

One solution to this might be to move your category to NSObject and make a bunch of checking. I did it like this:

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;

Ugly? Yes! But it works for now.

like image 1
NKorotkov Avatar answered Nov 05 '22 17:11

NKorotkov