カテゴリとしての文字列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
メソッド、私はfalseを取得します。
解決
return self == nil
これは決して起こり得ません。あなたが送信しようとすると isNullOrEmpty
(または他のメッセージ)に nil
, 、何も起こらない(objc_msgSend()
, 、メッセージのディスパッチを担当する関数は、 nil
それは最初のものの一つとして受信し、中止します)。
self == (id)[NSNull null]
これも決して起こりません。あなたが送信する場合 isNullOrEmpty
のインスタンスであるオブジェクトに NSNull
, 、ここであなたの方法は、上の方法です NSString
, 、呼び出されません。代わりに, NSNull
のバージョン(おそらく存在しない)になります。
同様に, ([self respondsToSelector:@selector(count)] && [(NSArray *) self count])
決して起こらないだろう。オブジェクトの場合 は an NSArray
, 、その後 isNullOrEmpty
実行されることはありません、なぜなら、再び、それはの方法です NSString
.
それに対応して, [(NSData *) self length]
あなたが思っていることをしません。 NSString
インスタンス do に応答する length
, 、しかし、オブジェクトをキャストする NSData
を使用しない NSData
メソッドのバージョン-それはまだ次のようになります NSString
のバージョン length
, 、オブジェクトなので 実際には an 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
.
他のヒント
もう1つの方法は、単純なマクロを定義することです。
#define NSStringIsNullOrEmpty(str) ((str==nil) || [(str) isEqualToString:@""])
.
簡単で効果的です。マクロが好きではない場合は、コードの残りの部分に影響を与えることなく、常にそれを関数呼び出しに変換することができます。
- 更新:
@bryanは良い点を上げました。インライン関数は、行くのに最適な方法です。これは一度だけstrを評価する更新されたマクロです。
#define NSStringIsNullOrEmpty(str) ({ NSString *_str=(str); ((tmp==nil) || [tmp isEqualToString:@""]);})
. Objective-Cでは、メッセージをNILに送信すると、常に0(または宣言された戻り型に応じて、ゼロドアウト構造、NULLなど)が常に返されます。NO
にisNullOrEmpty
を送信すると、書き込まれたisNullOrEmpty
メソッドは実際には呼び出されません。詳細については、
おそらくあなたはあなたのメソッドをnil
に変更することができました。その後、isNotNullOrEmpty
にisNotNullOrEmpty
を送信するときに0の戻り値が意味されます。
あなたはあなたのメソッドを呼び出していませんが、 nil にメッセージを送信します。
これは予想される行動です。あなたは結局のところnil
にメッセージを送信しています。だからそれはnil(または他の0の値)のどちらかを返します。次に示す場合には '0'が印刷されるように、
NSLog([s1 isNullOrEmpty] ? @"1":@"0"); // prints 0
NSLog([(NSString*)nil isNullOrEmpty] ? @"1":@"0"); // prints 0
.
新しいカテゴリメソッドにブレークポイントを設定することで、メッセージが呼び出されていないことを確認できます。
他の人が言ったように、Calling [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 *)NULLINPUTINITWITHSTRING :( NSSTRING *)INPUTSTRING {
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");
.