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

时间:2014-02-07 13:59:23

标签: ios categories nsurlsession

我想在NSURLSession上创建一个类别。该应用程序编译正常,但当我尝试调用类别方法时,我得到

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

很奇怪,这是我为了显示问题而构建的测试类。 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

4 个答案:

答案 0 :(得分:6)

我在后台NSURLSessionUploadTask s中得到了类似的结果,在__NSCFURLSessionUploadTask委托回调期间将其反序列化为-URLSession:task:didCompleteWithError:

如果我是你,我会放弃这种方法,并使用构图(即将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;
}

答案 1 :(得分:2)

如果您真的想要将类别添加到NSURLSession,这是一个替代解决方案。我从BETURLSession找到了这个解决方案。当然,您必须非常小心名称以避免名称冲突。

标题代码

#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];

答案 2 :(得分:0)

我试着和@ clay-bridges一样(即为每个任务存储一个userInfo NSDictionary),当使用会话配置与后台不同的NSURLSession时,它的效果很好。如果您使用带有后台配置的NSURLSession,并且您的应用已终止或崩溃,则上传/下载将在后台继续,由操作系统管理。上传/下载完成后,如果我尝试检索以前存储的userInfo NSDictionary,我什么也得不到。我的解决方案是使用NSDictionaryNSURLProtocol将自定义对象/ +setProperty:​forKey:​inRequest:存储在请求中,而不是任务中,稍后使用,检索信息:

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

答案 3 :(得分:-3)

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

#import "NSURLSession+test.h"