Я пробовал что-то вроде:
if(myString != nil && myString.length) { ... }
И получил:
- [NSNull length]: непризнанный селектор, отправленный в экземпляр
Не работает ли Objective-C короткое замыкание после первого условия?
Я пробовал что-то вроде:
if(myString != nil && myString.length) { ... }
И получил:
- [NSNull length]: непризнанный селектор, отправленный в экземпляр
Не работает ли Objective-C короткое замыкание после первого условия?
Objective-C поддерживает оценку короткого замыкания, как и C.
Кажется, что в вашем примере myString
есть NSNull
, а не nil
, поэтому myString != nil
- true.
NSNull является одноэлементным и используется для представления nil
, где допускаются только объекты, например, в NSArray.
Кстати, люди пишут if (!myString && myString.length == 0)
. Сравнение с nil
довольно уродливо. Кроме того, я бы сравнил длину с 0. Это кажется более понятным.
Objective-C является строгим надмножеством C.
Поскольку C поддерживает оценку короткого замыкания, Objective-C также делает.
Что определяет NSNull как? Если это объект, который, как предполагается, ничего не представляет, он не будет равен нулю. другими словами, NSNull и nil не совпадают.
Если у вас есть NSNull где-то, вы, вероятно, используете либо парсер JSON, либо CoreData. Когда число в CoreData не задано, CoreData вернет вам NSNull - возможно, то же самое относится и к значениям NSString в CoreData.
Аналогично, вы можете иметь пустые элементы в JSON, возвращенные с сервера, и некоторые парсеры дадут вам это как объект NSNull. Поэтому в обоих случаях вы должны быть осторожны, когда используете значения, поскольку предмет, который, по вашему мнению, был объектом NSString или NSNumber, действительно является NSNull.
Одним из решений является определение категории в NSNull, которая просто игнорирует все непонятные сообщения, отправленные объекту, в соответствии с приведенным ниже кодом. Тогда код, который у вас есть, будет работать, потому что NSNull.length вернет 0. Вы можете включить что-то вроде этого в ваш проект .pch файл, который включается в каждый отдельный файл вашего проекта.
// NSNull+IgnoreMessages.h
@interface NSNull(IgnoreMessages)
- (void)forwardInvocation:(NSInvocation *)anInvocation;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
@end
//NSNull+IgnoreMessages.m
#import "NSNull+IgnoreMessages.h"
@implementation NSNull(IgnoreMessages)
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if ( [self respondsToSelector:[anInvocation selector]] )
[anInvocation invokeWithTarget:self];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature *sig=[[NSNull class] instanceMethodSignatureForSelector:aSelector];
// Just return some meaningless signature
if(sig==nil)
sig=[NSMethodSignature signatureWithObjCTypes:"@^v^c"];
return sig;
}
@end