- [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
где-то...
Ответы
Ответ 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]]
.