- [NSNull length]: непризнанный селектор, отправленный объектам JSON - программирование
Подтвердить что ты не робот

- [NSNull length]: непризнанный селектор, отправленный объектам JSON

Я разрабатываю приложение iOS 5.0+ с последним SDK.

Я получаю очень странную ошибку с этим кодом:

- (NSMutableURLRequest*)setupRequestWithService:(NSString*)service andMethod:(NSString*)method
{
    NSString* url = [NSString stringWithFormat:@"%@%@.svc/%@", serverUrl, service, method];

    NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];

    // Set authentication token.
    NSLog(@"???????????? %@", authenticationToken);
    if (authenticationToken == nil)
        NSLog(@"NULL AUTHTOKEN");
    if ([authenticationToken isEqual:[NSNull null]])
        NSLog(@"NSNULL AUTHTOKEN");
    if (request == nil)
        NSLog(@"NULL REQUEST");
    [request addValue:authenticationToken forHTTPHeaderField:REQUEST_HEADER_AUTH_TOKEN];

    return request;
}

Это мой журнал:

???????????? <null>
NSNULL AUTHTOKEN
-[NSNull length]: unrecognized selector sent to instance 0x3b5a5090
    *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull length]: unrecognized selector sent to instance 0x3b5a5090'

Кажется, что authenticationToken есть NULL. Но я этого не понимаю, если authenticationToken есть NULL, почему я не вижу NULL AUTHTOKEN в журнале.

Я получаю эту ошибку во второй раз, когда запускаю этот метод, в первый раз я не получаю никаких ошибок. Это мой журнал:

???????????? (null)
NULL AUTHTOKEN

Кстати:

NSString* authenticationToken;

Любые советы?

Возможно, есть Memory Leak где-то...

4b9b3361

Ответ 1

Мое решение этого безумного использования NSNull интерпретаторами JSON заключается в создании категории в NSNull, где я определяю integerValue, floatValue, length и т.д. - возвращает 0 для всех. Каждый раз, когда вы получаете еще один крах, добавляйте новую категорию. Я думаю, что у меня было 6 или 7, когда у меня была эта проблема.

Проблема с НЕ делать это - вам нужно искать NULL везде в ваших преобразованных объектах - PITA, на мой взгляд.

EDIT: код, который я использую, все в файле NSNull + JSON.m:

@interface NSNull (JSON)
@end

@implementation NSNull (JSON)

- (NSUInteger)length { return 0; }

- (NSInteger)integerValue { return 0; };

- (float)floatValue { return 0; };

- (NSString *)description { return @"0(NSNull)"; }

- (NSArray *)componentsSeparatedByString:(NSString *)separator { return @[]; }

- (id)objectForKey:(id)key { return nil; }

- (BOOL)boolValue { return NO; }

@end

EDIT2: теперь в Swift 3:

extension NSNull {
   func length() -> Int { return 0 }

   func integerValue() -> Int { return 0 }

   func floatValue() -> Float { return 0 };

   open override var description: String { return "0(NSNull)" }

   func componentsSeparatedByString(separator: String) -> [AnyObject] { return [AnyObject]() }

   func objectForKey(key: AnyObject) -> AnyObject? { return nil }

   func boolValue() -> Bool { return false }
}

Ответ 2

Сообщение об ошибке довольно ясно. NSNull и nil - это разные вещи:

The NSNull class defines a singleton object used to represent null values in 
collection objects (which don’t allow nil values).

Если вы хотите проверить, есть ли authenticationToken NSNull try: [authenticationToken isEqual: [NSNull null]]

Ответ 3

В соответствии с ответом David H, как насчет категории на NSNull, которая просто использует пересылку сообщения ObjC для "ничего не делать", чтобы эмулировать поведение во время выполнения при отправке сообщений на nil?

Вот так:

@interface NSNull (ForwardInvocation)

@end

@implementation NSNull (ForwardInvocation)

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    return [NSNull methodSignatureForSelector:@selector(description)];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    // do nothing; prevent 'unrecognized selector' crashes
}

@end

[NSNull methodSignatureForSelector:@selector(description)]; использует тот факт, что NSNull наследует от NSObject, который предоставляет метод description. Это удовлетворяет требованию механизма пересылки для реализации -methodSignatureForSelector:.

Ответ 4

Проблема возникает из-за того, что ваш метод возвращает объект NSNull. Вы не можете проверить [authenticationToken isEqual:[NSNull null]]), потому что [NSNull null] дает экземпляр объекта. Так что это отличается от вашего объекта. Если вы хотите проверить, был ли вы получен объект NSNull, вам нужно проверить его следующим образом: [authenticationToken isKindOfClass:[NSNull class]].