String isNullOrEmpty 作为类别
-
14-12-2019 - |
题
我正在尝试创建一个方法来检查 null/nil/空字符串,并且我试图让它作为一个类别工作,但没有运气。
我正在使用这段代码,基于以下答案 这个话题:
@implementation NSString (NSStringExtension)
- (BOOL)isNullOrEmpty {
return self == nil ||
self == (id)[NSNull null] ||
[@"" isEqualToString:self] ||
[[self stringByReplacingOccurrencesOfString:@" " withString:@""] length] == 0||
[self isEqualToString:@"(null)"]
|| ([self respondsToSelector:@selector(length)] && [(NSData *) self length] == 0)
|| ([self respondsToSelector:@selector(count)] && [(NSArray *) self count] == 0)
|| [[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0;
}
@end
然而,当我尝试使用它时,我得到的是:
NSLog([@"" isNullOrEmpty] ? @"1":@"0"); // prints 1
NSString *s1 = nil;
NSLog([s1 isNullOrEmpty] ? @"1":@"0"); // prints 0
NSLog([args.itemName isNullOrEmpty] ? @"1":@"0"); // prints 0
NSLog([(NSString*)nil isNullOrEmpty] ? @"1":@"0"); // prints 0
这让我感到困惑,我只能假设 iOS5/ARC 的某种组合导致 nil 对象被强制为空字符串/指针。调试器将字符串显示为 0x0,但是当我使用我的 isNullOrEmpty
方法,我得到了错误。
解决方案
return self == nil
这永远不会发生。如果您尝试发送 isNullOrEmpty
(或任何其他消息)至 nil
, , 什么都没发生 (objc_msgSend()
, ,负责消息分发的函数,检查 nil
接收器作为它执行的第一件事之一并中止)。
self == (id)[NSNull null]
这也永远不会发生。如果您发送 isNullOrEmpty
到一个实例的对象 NSNull
, ,你的方法在这里,这是一个方法 NSString
, ,不会被调用。反而, NSNull
的版本(可能不存在)将会是。
同样地, ([self respondsToSelector:@selector(count)] && [(NSArray *) self count])
永远不会发生。如果物体 是 一个 NSArray
, , 然后 isNullOrEmpty
永远不会运行,因为,这又是一种方法 NSString
.
相应地, [(NSData *) self length]
不做你认为它做的事。 NSString
实例 做 回应 length
, ,但将对象投射到 NSData
不使用 NSData
该方法的版本——它最终仍然是 NSString
的版本 length
, ,因为对象 实际上是 一个 NSString
(转换仅发生在编译时;它不能在运行时改变任何东西)。
[self isEqualToString:@"(null)"]
在这里您似乎正在检查 nil
再次,但你被误导了 表示 那 NSLog
选择何时打印 nil
:
NSLog(@"%@", nil);
这显示 (null)
在控制台中,但这并不意味着对象本身是带有这些字符的字符串。 NSLog
只需选择要显示的字符串 nil
.*
您正在做的一些事情需要将其归入以下类别: NSObject
, ,使得该方法 会 事实上,即使该对象不是一个对象,也会被调用 NSString
.
要检查仅包含空格的字符串,您所需要做的就是与空字符串进行比较 @""
修剪空白后:
NSString * trimmedSelf = [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
// Then either:
[trimmedSelf isEqualToString:@""];
// Or:
([trimmedSelf length] == 0);
*甚至更好,做 NSLog(@"%@", [NSNull null]);
显示 <null>
(尖括号而不是圆括号),最初几次遇到时会令人非常困惑 NSNull
.
其他提示
另一种方法可以是定义一个简单的宏。
#define NSStringIsNullOrEmpty(str) ((str==nil) || [(str) isEqualToString:@""])
.
这很简单有效。如果您不喜欢宏,您可以随时将其转换为函数调用,而不会影响代码的其余部分。
- 更新:
@bryan提出了一个好点。内联功能是一种很好的方式。这是一个更新的宏,它只会评估str一次。
#define NSStringIsNullOrEmpty(str) ({ NSString *_str=(str); ((tmp==nil) || [tmp isEqualToString:@""]);})
. 在 Objective-C 中,向 nil 发送消息将始终返回 0(或 NO
, 、清零结构、NULL 等,具体取决于声明的返回类型)。这 isNullOrEmpty
您编写的方法在发送时实际上不会被调用 isNullOrEmpty
到 nil
. 。请参阅已接受的答案 向 nil 发送消息? 了解更多信息。
也许你可以改变你的方法 isNotNullOrEmpty
. 。那么发送时返回值为0 isNotNullOrEmpty
到 nil
会有道理的。
你没有调用你的方法,但是向nil 发送消息。
这是预期的行为。您正在发送消息至 nil
毕竟。所以它返回 nil (或其他 0 值)。哪个短路为假,以便在下面所示的情况下打印“0”:
NSLog([s1 isNullOrEmpty] ? @"1":@"0"); // prints 0
NSLog([(NSString*)nil isNullOrEmpty] ? @"1":@"0"); // prints 0
您甚至可以通过在新类别方法中设置断点来确认这些情况下不会调用您的消息。
就像其他人所说的那样,打电话 [nil isNullOrEmpty];
不会实际运行你的方法。这 nil
对象就是这样:本身就空了。
作为解决方案,我想说,并不是因为您使用的是面向对象语言,所以您就不能使用函数。
BOOL IsStringNilOrEmpty(NSString*)str
{
return str == nil ||
str == null ||
[@"" isEqualToString:str] ||
[[str stringByReplacingOccurrencesOfString:@" " withString:@""] length] == 0||
[str isEqualToString:@"(null)"]
|| ([str respondsToSelector:@selector(length)] && [(NSData *) str length] == 0)
|| ([str respondsToSelector:@selector(count)] && [(NSArray *) str count] == 0)
|| [[str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0;
}
实际上我只是通过像这样的方式转动它来修复这个问题
-(BOOL) isNotNullOrWhiteSpace
{
return [self length] != 0 && [[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] != 0;
}
.
所以它而不是IsnullorWhiteSpace它是IsnotnullorWhiteSpace。 这是我检查null /空的方法的方法
- (nsstring *)nullinputinitwithtring :( nsstring *)输入体 {
if( (InputString == nil) ||(InputString ==(NSString*)[NSNull null])||([InputString isEqual:nil])||([InputString length] == 0)||([InputString isEqualToString:@""])||([InputString isEqualToString:@"(NULL)"])||([InputString isEqualToString:@"<NULL>"])||([InputString isEqualToString:@"<null>"]||([InputString isEqualToString:@"(null)"])||([InputString isEqualToString:@"NULL"]) ||([InputString isEqualToString:@"null"])))
return @"";
else
return InputString ;
.
}
您是否考虑过在扩展NSString的类别上创建类方法?
nsstring + nsstringextensions.h
#import <Foundation/Foundation.h>
@interface NSString(NSStringExtensions)
+(BOOL)isNilOrEmpty:(NSString*)string;
@end
.
nsstring + nsstringextensions.m
#import "NSString+NSStringExtensions.h"
@implementation NSString(NSStringExtensions)
+(BOOL)isNilOrEmpty:(NSString*)string
{
if (nil == string)
{
return YES;
}
if (string.length == 0)
{
return YES;
}
return NO;
}
@end
.
然后你使用它:
#import "NSString+NSStringExtensions.h"
...
NSLog([NSString isNilOrEmpty:@""] ? @"1":@"0");
.