2014-02-07 50 views
12

我想在NSURLSession上創建一個類別。該應用程序編譯好了,但是當我試圖調用類的方法,我得到iOS:在運行時未找到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 

回答

6

我有類似的結果與中背景NSURLSessionUploadTask s,這反序列化時,你必須導入自定義類別作爲__NSCFURLSessionUploadTask s在-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

沒錯。我已經重新編寫了使用組合。儘管如此,我仍然對好奇心很好奇。 Bug報告給蘋果公司。 – drekka

+0

你有沒有在這個問題上找到更多的東西?我有同樣的問題。蘋果對你的錯誤報告有何迴應?如果可能的話,我希望能夠使用一個類別。 – stevekohls

+0

@drekka:你可以在蘋果論壇上發佈bug鏈接嗎?即使我面臨類似的問題,也無法從iOS7中調用任何自定義的NSURLSession子類/類別方法。它在> = iOS8中工作正常。無論如何,請讓我知道你是否可以幫助我。 –

-3

,你調用自定義方法

#import "NSURLSession+test.h" 
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]; 
+1

問題是NSURLSession對象正在轉換爲它們的Core Foundation對應物。使用這種方法仍然不會讓您與類別方法內的自我對象進行交互。 – mph

+0

@jqyao他已經在他的代碼中提到我們不能在NSURLSession上做類別所以請在NSObject上做類別。 –

+0

這是一個相當有點破解,但它確實有效。要訪問類別方法內的NSURLSession方法,請驗證該對象是否爲NSURLSession,然後創建一個局部變量,該變量將自我轉換爲NSURLSession。 – SwampThingTom

0

我試圖做的一樣@泥橋(即爲每個任務存儲用戶信息NSDictionary),並且在將會話與NSURLSession一起使用時效果很好配置與背景不同。如果您使用NSURLSession背景配置,並且您的應用程序被終止或崩潰,則上傳/下載將在後臺繼續,由OS管理。當上傳/下載完成時,如果我嘗試檢索先前存儲的userInfo NSDictionary,我什麼也沒得到。我的解決方案是該自定義對象/ NSDictionary存儲在要求,沒有任務,使用NSURLProtocol+setProperty:​forKey:​inRequest:,後來,檢索使用的信息:

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