Cách đúng để kiểm tra chuỗi null trong Objective-C là gì?


184

Tôi đã sử dụng điều này trong ứng dụng iPhone của tôi

if (title == nil) {
    // do something
}

nhưng nó đưa ra một số ngoại lệ và bảng điều khiển cho thấy tiêu đề là "(null)".

Vì vậy, tôi đang sử dụng điều này ngay bây giờ:

if (title == nil || [title isKindOfClass:[NSNull class]]) {
    //do something
}

Sự khác biệt là gì và cách tốt nhất để xác định xem một chuỗi có là null không?


Câu trả lời:


395

Như những người khác đã chỉ ra, có rất nhiều loại "null" trong Ca cao / Mục tiêu C. Nhưng một điều nữa cần lưu ý là [title isKindOfClass: [NSNull class]] rất phức tạp vì [NSNull null] được ghi nhận là một singleton để bạn có thể kiểm tra sự bằng nhau của con trỏ. Xem chủ đề cho ca cao: Sử dụng Null .

Vì vậy, một bài kiểm tra tốt có thể là:

if (title == (id)[NSNull null] || title.length == 0 ) title = @"Something";

Lưu ý cách bạn có thể sử dụng thực tế là ngay cả khi tiêu đề là nil, title.length sẽ trả về 0 / nil / false, tức là 0 trong trường hợp này, vì vậy bạn không phải trường hợp đặc biệt. Đây là điều mà những người mới sử dụng Objective C gặp khó khăn trong việc làm quen, đặc biệt là đến các ngôn ngữ khác nơi các thông điệp / phương thức gọi đến không gặp sự cố.


Cảm ơn! Tuy nhiên tôi đã hỏi câu hỏi này ngay từ đầu vì tôi nhận được ngoại lệ vì "tiêu đề" null.
Teo Choong Ping

1
Loại tiêu đề được cho là gì? Ví dụ, nếu đó là NSString, tôi nhận được cảnh báo sau: so sánh các loại Objective-C khác nhau 'struct NSNull *' và 'struct NSString *' thiếu một diễn viên Có cách nào để loại bỏ điều này không (tôi không biết nếu mọi thứ đã thay đổi kể từ đó câu hỏi này đã được hỏi)?
thebossman

1
Phục vụ tôi ngay để đăng mã mà không cần biên dịch mã ;-). tiêu đề có lẽ là một NSString, nhưng bất kể loại tiêu đề nào, chỉ chuyển null thành loại id chung: (id) [NSNull null].
Peter N Lewis

1
@JLT nil và [NSNull null] sẽ không bao giờ giống nhau. [NSNull null] là một đối tượng đơn lẻ có thể được sử dụng làm giá trị thay thế cho nil khi không thể sử dụng nil (ví dụ: trong giá trị NSArray hoặc NSDipedia). Vì vậy, trường hợp sử dụng có thể là nơi bạn có NSArray của các chuỗi tùy chọn, một số chuỗi có thể là null và bạn sử dụng [NSNull null] trong mảng cho các trường hợp null. Trong thực tế, kiểm tra hiếm khi cần thiết, chỉ khi bạn (hoặc thư viện bạn sử dụng!) Chủ động sử dụng [NSNull null] làm trình giữ chỗ.
Peter N Lewis

1
Đến đây từ Flutter, và tìm kiếm lý do tại sao Mapgiá trị của một vật phẩm - có nulltrong Dart - không tương ứng nilhoặc NULLtrong Mục tiêu C. Lý do là nó thực sự NUNull null, không phải là NULLnull. Cảm ơn bạn @PeterNLewis!
Alexandar

25

nó chỉ đơn giản như

if([object length] >0)
{
  // do something
}

hãy nhớ rằng trong mục tiêu C nếu đối tượng là null, nó trả về 0 làm giá trị.

Điều này sẽ giúp bạn có cả chuỗi null và chuỗi có độ dài 0.


49
Điều này sẽ không hoạt động nếu đối tượng là NSNull, vẫn cần kiểm tra rõ ràng trước.
Jeremy Mack

6
bạn cũng có thể tạo một danh mục cho NSNull để làm cho nó trở về 0 với thông báo độ dài :)
Mihai Timar

1
Phải, điều này sẽ sụp đổ nếu đối tượng là NSNull.
Mike Gledhill

Điều này sẽ sụp đổ nếu đối tượng bằng NSNull
joan

1
Ngoài vấn đề về bộ chọn không được nhận dạng NSNull, vấn đề này sẽ không phân biệt giữa một con trỏ NSString không, hoặc một NSString thực sự ở đó nhưng về cơ bản là một chuỗi rỗng. (Ví dụ như một nghĩa đen object = @"";hoặc object = nil;)
KellyTheDude

6

Tham khảo các bài viết liên quan sau đây trên trang web này:

Tôi nghĩ rằng lỗi của bạn có liên quan đến một cái gì đó khác vì bạn không cần phải kiểm tra thêm.

Cũng xem câu hỏi liên quan này: Kiểm tra đúng cột văn bản nil sqlite


Khó chịu là tôi không có đủ "điểm" để thêm siêu liên kết thứ hai (thậm chí vào một cái gì đó trên trang web này) xem thêm: - stackoverflow.com/questions/598394/
Thẻ

...cho phép tôi. Mặc dù bạn có thể chỉnh sửa bài đăng của mình từ đại diện 0.
Rog

Cảm ơn - đó là rất tốt. Khi tôi viết bài đăng đầu tiên của mình, nó nói một cái gì đó như người dùng mới chỉ có thể thêm 1 siêu liên kết (có vẻ hơi khắc nghiệt - đặc biệt là đối với các liên kết chéo trong trang web này).
TimM

6

Tôi đã thấy rằng để thực sự làm đúng, cuối cùng bạn phải làm một cái gì đó tương tự như

if ( ( ![myString isEqual:[NSNull null]] ) && ( [myString length] != 0 ) ) {
}

Nếu không, bạn nhận được các tình huống kỳ lạ trong đó kiểm soát vẫn sẽ bỏ qua kiểm tra của bạn. Tôi đã không bắt gặp một cái mà vượt qua isEqualkiểm tra và độ dài.


5

Điều gì với tất cả những "câu trả lời cho tôi"? Tất cả chúng ta đều viết mã trong cùng một ngôn ngữ và các quy tắc là

  1. Đảm bảo các tài liệu tham khảo không phải là con số không
  2. Kiểm tra và đảm bảo độ dài của chuỗi không bằng 0

Đó là những gì sẽ làm việc cho tất cả. Nếu một giải pháp nhất định chỉ "phù hợp với bạn", thì đó chỉ là do luồng ứng dụng của bạn sẽ không cho phép một kịch bản trong đó tham chiếu có thể là null hoặc độ dài chuỗi là 0. Cách phù hợp để thực hiện điều này là phương thức sẽ xử lý những gì bạn muốn trong mọi trường hợp.


4
Nếu tham chiếu là nil(lưu ý: không phải "null"), thì việc gửi tin nhắn, như length, sẽ tạo ra 0 (hoặc giá trị 0 thích hợp cho kiểu trả về của phương thức). Đó là quy tắc của ngôn ngữ. Không cần phải kiểm tra nilriêng trong trường hợp này.
jscs

Tôi đã nói null đơn giản chỉ vì thói quen của C ++ và nếu mã của bạn đang gọi các phương thức trên các đối tượng không, thì rất có thể mã của bạn bị hỏng. Bạn sẽ thấy rằng các phương thức gọi trên NULL / NIL (cùng một khái niệm) nói chung là một ý tưởng tồi trong bất kỳ ngôn ngữ nào. Chỉ vì obj-c cho phép bạn làm điều gì đó không có nghĩa là bạn chỉ nên đi xung quanh các đối tượng không và cố gắng sử dụng chúng mà không cần quan tâm.
nenchev

1
Gửi chiều dài đến 0 không tạo ra 0 - NHƯNG chiều dài gửi tới NSNull tạo ra một ngoại lệ.
cdstamper

@nenchev Không ai nói bất cứ điều gì về việc chỉ đi xung quanh các đối tượng không, nhưng kiểm tra nil, sau đó gọi một phương thức và sử dụng giá trị trả về của nó là IMO tệ hơn là sử dụng một tính năng ngôn ngữ như nó được sử dụng và kiểm tra tính hợp lệ của giá trị trả về của phương thức sau đó.
Kevin

@Kevin Tôi không chắc nó tệ đến mức nào, chỉ vì tính năng ngôn ngữ của nó không có nghĩa là nó tuyệt vời. Không kiểm tra xem null của nó có thể mở ra một đường dẫn mã có thể dẫn đến lỗi theo dõi thời gian chạy khó hơn không. Thông thường tốt nhất để xác minh rằng đầu vào của bạn là như bạn mong đợi, và phản ứng tương ứng nếu không. Cá nhân tôi không thích "tính năng" của việc không nhận được ngoại lệ trong thời gian chạy khi cố gắng gửi tin nhắn đến một đối tượng không, vì nó thường dễ bỏ sót một số lỗi thời gian chạy.
nenchev

4

Nếu bạn muốn kiểm tra tất cả các đối tượng nil / trống (như chuỗi rỗng hoặc mảng / bộ trống), bạn có thể sử dụng như sau:

static inline BOOL IsEmpty(id object) {
    return object == nil
        || ([object respondsToSelector:@selector(length)]
        && [(NSData *) object length] == 0)
        || ([object respondsToSelector:@selector(count)]
        && [(NSArray *) object count] == 0);
}

2
Điều này không thực sự kiểm tra đối tượng == [NSNull null] có thể có ý nghĩa.
Peter N Lewis

3

Có hai tình huống:

Có thể là một đối tượng [NSNull null], hoặc là không thể.
Ứng dụng của bạn thường không nên sử dụng [NSNull null];bạn chỉ sử dụng nó nếu bạn muốn đặt một đối tượng " null " vào một mảng hoặc sử dụng nó làm giá trị từ điển. Và sau đó bạn nên biết mảng nào hoặc từ điển có thể chứa giá trị null và cái nào có thể không.
Nếu bạn nghĩ rằng một mảng không bao giờ chứa [NSNull null]các giá trị, thì đừng kiểm tra nó. Nếu có [NSNull null], bạn có thể nhận được một ngoại lệ nhưng điều đó là tốt: ngoại lệ Objective-C chỉ ra lỗi lập trình. Và bạn có một lỗi lập trình cần sửa bằng cách thay đổi một số mã.

Nếu một đối tượng thể [NSNull null], thì bạn kiểm tra điều này khá đơn giản bằng cách thử nghiệm
(object == [NSNull null]). Gọi isEqualhoặc kiểm tra lớp của đối tượng là vô nghĩa. Chỉ có một [NSNull null]đối tượng và toán tử C cũ đơn giản kiểm tra xem nó có ổn không theo cách đơn giản và hiệu quả nhất.

Nếu bạn kiểm tra một NSStringđối tượng không thể[NSNull null] (vì bạn biết nó không thể [NSNull null]hoặc vì bạn chỉ kiểm tra xem nó có khác không [NSNull null], thì bạn cần tự hỏi mình muốn xử lý một chuỗi rỗng như thế nào, đó là một chuỗi có độ dài 0. Nếu bạn coi nó là một nullchuỗi như thế nil, sau đó kiểm tra (object.length == 0). object.length sẽ trả về 0 nếu object == nil, vì vậy kiểm tra này bao gồm các đối tượng và chuỗi không có độ dài 0. Nếu bạn xử lý một chuỗi có độ dài 0 khác với chuỗi nil, chỉ cần kiểm tra xem object == nil.

Cuối cùng, nếu bạn muốn thêm một chuỗi vào một mảng hoặc một từ điển và chuỗi đó có thể là không, bạn có thể chọn không thêm nó, thay thế nó bằng @""hoặc thay thế nó bằng [NSNull null]. Thay thế nó bằng @""có nghĩa là bạn mất khả năng phân biệt giữa "không có chuỗi" và "chuỗi có độ dài 0". Thay thế nó bằng[NSNull null] có nghĩa là bạn phải viết mã khi bạn truy cập vào mảng hoặc từ điển kiểm tra [NSNull null]các đối tượng.


Rất dài, nhưng điều này là tốt. NSNull chỉ nên xuất hiện trong SINGLETONS! Toàn bộ câu hỏi này không có ý nghĩa gì, nói với tôi rằng lập trình viên đã không làm điều gì đó chính xác, và nhiều điều nữa trong tương lai cũng vậy, đã không đọc hướng dẫn / thực hành mã tốt
Stephen J

2

Bạn chỉ cần kiểm tra cho không

if(data[@"Bonds"]==nil){
  NSLog(@"it is nil");
}

hoặc là

if ([data[@"Bonds"] isKindOfClass:[NSNull class]]) {
    NSLog(@"it is null");
}

2

Giải pháp MACRO (2020)

Đây là macro mà tôi sử dụng cho chuỗi an toàn thay vì nhận chuỗi " (null) " trên UILabel chẳng hạn:

#define SafeString(STRING) ([STRING length] == 0 ? @"" : STRING)

giả sử bạn có một lớp thành viên và thuộc tính name và tên là nil:

NSLog(@"%@", member.name); // prints (null) on UILabel

với vĩ mô:

NSLog(@"%@", SafeString(member.name)); // prints empty string on UILabel

đẹp và sạch sẽ

Giải pháp mở rộng (2020)

Nếu bạn thích kiểm tra null Null và chuỗi rỗng trong dự án của bạn, bạn có thể sử dụng dòng mở rộng của tôi bên dưới:

NSString + Gia hạn.h

///
/// Checks if giving String is an empty string or a nil object or a Null.
/// @param string string value to check.
///
+ (BOOL)isNullOrEmpty:(NSString*)string;

NSString + Gia hạn.m

+ (BOOL)isNullOrEmpty:(NSString*)string {
    if (string) { // is not Nil
        NSRange range = [string rangeOfString:string];
        BOOL isEmpty = (range.length <= 0 || [string isEqualToString:@" "]);
        BOOL isNull = string == (id)[NSNull null];

        return (isNull || isEmpty);
    }

    return YES;
}

Cách sử dụng ví dụ

if (![NSString isNullOrEmpty:someTitle]) {
    // You can safely use on a Label or even add in an Array for example. Remember: Arrays don't like the nil values!
}



1
@interface NSString (StringFunctions)
- (BOOL) hasCharacters;
@end

@implementation NSString (StringFunctions)
- (BOOL) hasCharacters {
    if(self == (id)[NSNull null]) {
        return NO;
    }else {
        if([self length] == 0) {
            return NO;
        }
    }
    return YES;
}
@end

NSString *strOne = nil;
if([strOne hasCharacters]) {
    NSLog(@"%@",strOne);
}else {
    NSLog(@"String is Empty");
}

Điều này sẽ làm việc với các trường hợp sau, NSString *strOne = @""HOẶC NSString *strOne = @"StackOverflow"HOẶC NSString *strOne = [NSNull null]HOẶC NSString *strOne.


0

Nếu loại điều đó chưa tồn tại, bạn có thể tạo một danh mục NSString:

@interface NSString (TrucBiduleChoseAdditions)

- (BOOL)isEmpty;

@end

@implementation NSString (TrucBiduleChoseAdditions)

- (BOOL)isEmpty {
    return self == nil || [@"" isEqualToString:self];
}

@end

Điều đó có thể quá mức cần thiết và tôi không nghĩ rằng nó sẽ giải quyết vấn đề này.
Rog

9
Cái tôi == nil là vô nghĩa - nếu bản thân là con số không, Mục tiêu C sẽ không gọi bạn ngay từ đầu. [(NSString *) nil isEmpty] sẽ chỉ trả về 0 / nil / false mà không cần gọi mã của bạn.
Peter N Lewis

4
Trên thực tế, xa hơn nữa, [(NSString *) nil isEmpty] sẽ trả về false. Khi viết các phương thức Objective C như vậy, tốt hơn là xác định chúng sao cho 0 / nil / false của nil có ý nghĩa, vì vậy viết phương thức dưới dạng hasChar character sẽ tốt hơn. Lưu ý rằng độ dài đã hoạt động cho điều này, vì bạn có thể sử dụng if (s.length) bất cứ nơi nào bạn muốn sử dụng if (! S.isEmpty) và s.length sẽ trả về 0 chính xác cho trường hợp s == nil.
Peter N Lewis

Đây là một vụ tai nạn nghiêm trọng. Bạn đã triển khai "isEmpty" cho NSString, nhưng nếu đó thực sự là NSNull, thì isEmpty sẽ được gửi tới NSNull và gặp sự cố vì nó không phản hồi thông báo đó!
daniel.gindi

0

Những gì làm việc cho tôi là if ( !myobject )


3
Điều đó không làm việc cho các đối tượng null, chỉ các đối tượng không. Ví dụ ... NSArray *testarray = [NSArray arrayWithObjects:[NSNull null],@"", nil]; NSString *string = [testarray objectAtIndex:0]; NSLog(@"null string value: %@",string); if (!string) { NSLog(@"string evaluates to null"); } if (string && (string==(id)[NSNull null])) { NSLog(@"string does not evaluate to null"); }
Rik Smith-Unna

Err .. xin lỗi về định dạng, nhưng mã sẽ biên dịch :)
Rik Smith-Unna

0

Việc kiểm tra toàn bộ chuỗi cho các điều kiện null có thể như sau: <\ br>

    nếu (bí ẩn)
     {
       if ([mystring isEqualToString: @ ""])
        {
          mystring = @ "một số chuỗi";
        }
     }    
    khác
     {
        //các câu lệnh
     }

0

Tôi chỉ kiểm tra chuỗi null với

if ([myString isEqual: [NSNull null]])


0
if ([linkedStr isEqual:(id)[NSNull null]])
                {
                    _linkedinLbl.text=@"No";
                }else{
                    _linkedinLbl.text=@"Yes";
                }

1
Mặc dù đoạn mã này có thể trả lời câu hỏi, nó không cung cấp bất kỳ ngữ cảnh nào để giải thích làm thế nào hoặc tại sao. Xem xét thêm một hoặc hai câu để giải thích câu trả lời của bạn.
brandonscript

0
if ([strpass isEqual:[NSNull null]] || strpass==nil || [strpass isEqualToString:@"<null>"] || [strpass isEqualToString:@"(null)"] || strpass.length==0 || [strpass isEqualToString:@""])
{
    //string is blank  
}

0

Đối với chuỗi:

+ (BOOL) checkStringIsNotEmpty:(NSString*)string {
if (string == nil || string.length == 0) return NO;
return YES;

}

Tham khảo hình dưới đây:

nhập mô tả hình ảnh ở đây


0

Đối với chuỗi:

+ (BOOL) checkStringIsNotEmpty:(NSString*)string {
if (string == nil || string.length == 0) return NO;
return YES;}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.