iOS:在运行时找不到NSURLSession类别的方法

我想在NSURLSession上创build一个类别。 该应用程序编译好,但是当我试图调用我得到的类别方法

-[__NSCFURLSession doSomething]: unrecognized selector sent to instance 0xbf6b0f0 <unknown>:0: error: -[NSURLSession_UPnPTests testCategory] : -[__NSCFURLSession doSomething]: unrecognized selector sent to instance 0xbf6b0f0 

很奇怪,这里是一个testing课,我用来展示这个问题。 NSString类别工作正常,但NSURLSession类别在运行时找不到方法。 我怀疑这是内在的东西。

意见请:-)

 #import <XCTest/XCTest.h> @interface NSString (test) -(void) doSomethingHere; @end @implementation NSString (test) -(void) doSomethingHere { NSLog(@"Hello string"); } @end @interface NSURLSession (test) -(void) doSomething; @end @implementation NSURLSession (test) -(void) doSomething { NSLog(@"Hello!!!!"); } @end @interface NSURLSession_UPnPTests : XCTestCase @end @implementation NSURLSession_UPnPTests -(void) testCategory { [@"abc" doSomethingHere]; NSURLSession *session = [NSURLSession sharedSession]; [session doSomething]; } @end 

我有类似的结果与NSURLSessionUploadTask背景,在-URLSession:task:didCompleteWithError:委托callback过程中,它被反序列化为__NSCFURLSessionUploadTask

如果我是你,我会放弃这种做法,并使用组合(即使NSURLSession在另一个对象中NSURLSession一个ivar)。 如果您需要使用NSURLSession存储一些信息,则可以将一个JSON编码的字典填充到.sessionDescription

以下是我用来完成任务的代码:

 #pragma mark - Storing an NSDictionary in NSURLSessionTask.description // This lets us attach some arbitrary information to a NSURLSessionTask by JSON-encoding // an NSDictionary, and storing it in the .description field. // // Attempts at creating subclasses or categories on NSURLSessionTask have not worked out, // because the –URLSession:task:didCompleteWithError: callback passes an // __NSCFURLSessionUploadTask as the task argument. This is the best solution I could // come up with to store arbitray info with a task. - (void)storeDictionary:(NSDictionary *)dict inDescriptionOfTask:(NSURLSessionTask *)task { NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil]; NSString *stringRepresentation = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; [task setTaskDescription:stringRepresentation]; [stringRepresentation release]; } - (NSDictionary *)retrieveDictionaryFromDescriptionOfTask:(NSURLSessionTask *)task { NSString *desc = [task taskDescription]; if (![desc length]) { DDLogError(@"No description for %@", task); return nil; } NSData *data = [desc dataUsingEncoding:NSUTF8StringEncoding]; NSDictionary *dict = (data ? (id)[NSJSONSerialization JSONObjectWithData:data options:0 error:nil] : nil); if (!dict) { DDLogError(@"Could not parse dictionary from task %@, description\n%@", task, desc); } return dict; } 

如果你真的想把类添加到NSURLSession中,这是一个替代解决scheme。 我从BETURLSession中find了这个解决scheme。 当然,你必须非常小心名称,以避免名称冲突。

代码为标题

 #import <Foundation/Foundation.h> @interface NSURLSession (YTelemetry) -(void) hello; @end 

实施守则

 #import "NSURLSession+YTelemetry.h" @implementation NSObject (YTelemetry) -(void) hello { NSLog(@"hello world"); } @end 

现在在代码中,我可以

 NSURLSession *session = [NSURLSession sharedSession]; [session hello]; 

我试图做@粘土桥(即为每个任务存储一个userInfo NSDictionary )相同,并使用NSURLSession与会议configuration不同于背景时,它的作品很好。 如果您使用带有后台configuration的NSURLSession ,并且您的应用程序被终止或崩溃,则上传/下载将在后台继续,由操作系统pipe理。 当上传/下载完成时,如果我尝试检索先前存储的userInfo NSDictionary ,我什么也得不到。 我的解决scheme是使用NSURLProtocol+setProperty:​forKey:​inRequest:请求中存储自定义对象/ NSDictionary ,而不是任务,并且稍后使用以下方法检索信息:

id customObject = [NSURLProtocol propertyForKey:@"yourkey" inRequest:sessionTask.originalRequest];

您必须在您调用自定义方法的位置导入自定义类别

 #import "NSURLSession+test.h"