Подтвердить что ты не робот

IOS: методы категории 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
4b9b3361

Ответ 1

У меня были аналогичные результаты с backgrounded 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;
}

Ответ 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];

Ответ 3

Я попытался сделать то же самое, что и @clay-мосты (т.е. сохранить userInfo NSDictionary для каждой задачи), и он отлично работает при использовании NSURLSession с конфигурацией сеанса, отличной от фона. Если вы используете конфигурацию NSURLSession с конфигурацией фон, и ваше приложение завершается или сбой, загрузка/загрузка продолжается в фоновом режиме, управляемом ОС. Когда загрузка/загрузка заканчивается, если я пытаюсь восстановить ранее сохраненную пользовательскую информацию NSDictionary, я ничего не получаю. Мое решение состоит в том, чтобы сохранить этот пользовательский объект /NSDictionary в запросе, а не в задаче, используя NSURLProtocol: +setProperty:​forKey:​inRequest:, а затем получить информацию с помощью:

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

Ответ 4

вы должны импортировать свою настраиваемую категорию, где вы вызываете пользовательские методы

#import "NSURLSession+test.h"