Apa cara yang benar untuk memeriksa string null di Objective-C?


184

Saya menggunakan ini di aplikasi iPhone saya

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

tetapi ada beberapa pengecualian, dan konsol menunjukkan bahwa judulnya adalah "(nol)".

Jadi saya menggunakan ini sekarang:

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

Apa perbedaannya, dan apa cara terbaik untuk menentukan apakah suatu string adalah nol?


Jawaban:


395

Seperti yang telah ditunjukkan oleh orang lain, ada banyak jenis "null" di bawah Cocoa / Objective C. Tetapi satu hal lagi yang perlu diperhatikan adalah bahwa [judul isKindOfClass: [NSNull class]] tidak ada gunanya kompleks karena [NSNull null] didokumentasikan menjadi singleton sehingga Anda bisa memeriksa kesetaraan pointer. Lihat Topik untuk Kakao: Menggunakan Null .

Jadi tes yang bagus mungkin:

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

Perhatikan bagaimana Anda dapat menggunakan fakta bahwa meskipun judul adalah nihil, title.length akan mengembalikan 0 / nil / false, yaitu 0 dalam kasus ini, jadi Anda tidak perlu membuat huruf khusus. Ini adalah sesuatu yang orang-orang yang baru ke Objective C kesulitan membiasakan diri, terutama datang dari bahasa lain di mana pesan / metode panggilan ke nil crash.


Terima kasih! Namun saya menanyakan pertanyaan ini sejak awal karena saya mendapatkan pengecualian karena "judul" nol.
Teo Choong Ping

1
Apa jenis judul seharusnya? Jika itu NSString, misalnya, saya menerima peringatan berikut: perbandingan tipe Objective-C berbeda 'struct NSNull *' dan 'struct NSString *' tidak memiliki gips. Apakah ada cara untuk menghapus ini (saya tidak tahu apakah ada perubahan sejak itu pertanyaan ini ditanyakan)?
thebossman

1
Melayani saya tepat untuk memposting kode tanpa mengompilasinya ;-). judul mungkin merupakan NSString, tetapi terlepas dari jenis judulnya, cukup masukkan nol ke jenis id umum: (id) [NSNull null].
Peter N Lewis

1
@ JLT nihil dan [NSNull null] tidak akan pernah sama. [NSNull null] adalah objek tunggal yang dapat digunakan sebagai pengganti nil saat nil tidak dapat digunakan (misalnya dalam nilai NSArray atau NSDictionary). Jadi use case mungkin di mana Anda memiliki NSArray string opsional, beberapa di antaranya mungkin nol, dan Anda menggunakan [NSNull null] dalam array untuk case-case null. Dalam praktiknya, tes ini jarang diperlukan, hanya ketika Anda (atau perpustakaan yang Anda gunakan!) Secara aktif menggunakan [NSNull null] sebagai pengganti.
Peter N Lewis

1
Datang ke sini dari Flutter, dan mencari alasan mengapa nilai Mapitem - yang ada nulldi Dart - tidak sesuai dengan nilatau NULLdi Objective C. Alasannya adalah sebenarnya NUNull null, bukan NULLnol. @PeterNLewis Terima Kasih
Aleksandar

25

hanya sesederhana

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

ingat bahwa dalam tujuan C jika objek bernilai nol mengembalikan 0 sebagai nilai.

Ini akan membuat Anda menjadi string nol dan string 0 panjang.


49
Ini tidak akan berfungsi jika objek NSNull, masih perlu memeriksa secara eksplisit terlebih dahulu.
Jeremy Mack

6
Anda juga bisa membuat kategori untuk NSNull untuk membuatnya mengembalikan 0 ke panjang pesan :)
Mihai Timar

1
Yup, ini akan macet jika objeknya NSNull.
Mike Gledhill

Ini akan macet jika objek sama dengan NSNull
joan

1
Selain masalah pemilih NSNull yang tidak dikenali, ini tidak akan membedakan antara pointer NSString yang nihil, atau NSString yang sebenarnya ada tetapi pada dasarnya adalah string kosong. (Misalnya sebagai literal object = @"";atauobject = nil; )
KellyTheDude

6

Lihat artikel terkait berikut di situs ini:

Saya pikir kesalahan Anda terkait dengan sesuatu yang lain karena Anda tidak perlu melakukan pemeriksaan tambahan.

Lihat juga pertanyaan terkait ini: Pemeriksaan kolom teks nl sqlite yang benar


Menjengkelkan saya tidak punya cukup "poin" untuk menambahkan hyperlink kedua (bahkan untuk sesuatu di situs ini) lihat juga: - stackoverflow.com/questions/598396/…
TimM

...izinkan saya. Meskipun Anda harus dapat mengedit posting Anda sendiri dari rep 0.
Rog

Terima kasih - itu sangat baik. Ketika saya menulis posting awal saya mengatakan sesuatu seperti pengguna baru hanya dapat menambahkan 1 hyperlink (yang tampaknya agak keras - terutama untuk tautan silang di situs ini).
TimM

6

Saya telah menemukan bahwa untuk benar-benar melakukannya Anda akhirnya harus melakukan sesuatu yang mirip

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

Kalau tidak, Anda mendapatkan situasi aneh di mana kontrol akan tetap memotong cek Anda. Saya belum menemukan satu yang membuatnya melewati isEqualdan panjang pemeriksaan.


5

Whats dengan semua ini "berfungsi untuk saya jawaban"? Kita semua mengkode dalam bahasa yang sama dan aturannya adalah

  1. Pastikan referensi tidak nol
  2. Periksa dan pastikan panjang string tidak 0

Itulah yang akan berhasil untuk semua. Jika solusi yang diberikan hanya "bekerja untuk Anda", itu hanya karena aliran aplikasi Anda tidak akan memungkinkan untuk skenario di mana referensi mungkin nol atau panjang string menjadi 0. Cara yang tepat untuk melakukan ini adalah metode yang akan menangani apa yang Anda inginkan dalam semua kasus.


4
Jika referensi adalah nil(catatan: bukan "null"), maka mengirim pesan, seperti length, akan menghasilkan 0 (atau nilai 0 yang sesuai untuk jenis pengembalian metode). Itulah aturan bahasanya. Tidak perlu memeriksa secara nilterpisah dalam hal ini.
jscs

Saya katakan nol hanya karena kebiasaan C ++, dan jika kode Anda memanggil metode pada objek nil, kemungkinan kode Anda rusak. Anda akan menemukan bahwa metode memanggil pada NULL / NIL (konsep yang sama) umumnya merupakan ide yang buruk dalam bahasa apa pun. Hanya karena obj-c memungkinkan Anda melakukan sesuatu seperti itu tidak berarti Anda hanya harus melewati objek nihil dan mencoba menggunakannya tanpa peduli.
nenchev

1
Mengirim panjang ke nol tidak menghasilkan 0 - TETAPI panjang pengiriman ke NSNull menghasilkan pengecualian.
cdstamper

@nenchev Tidak ada yang mengatakan apa-apa tentang hanya membagikan objek nihil, tetapi memeriksa nihil, kemudian memanggil metode dan menggunakan nilai pengembaliannya IMO lebih buruk daripada menggunakan fitur bahasa seperti itu dimaksudkan untuk digunakan dan memeriksa validitas nilai kembali metode setelah itu.
Kevin

@ Kevin Saya tidak yakin seberapa parahnya, hanya karena fitur bahasanya tidak berarti bagus. Tidak memeriksa apakah nolnya dapat membuka jalur kode yang dapat menyebabkan kesalahan runtime yang lebih sulit dilacak. Biasanya yang terbaik adalah memverifikasi bahwa input Anda seperti yang Anda harapkan, dan bereaksi sesuai jika tidak. Secara pribadi saya tidak suka "fitur" untuk tidak mendapatkan run-time exception ketika mencoba mengirim pesan ke objek nil, karena seringkali membuatnya lebih mudah untuk melewatkan beberapa bug runtime.
nenchev

4

Jika Anda ingin menguji terhadap semua benda kosong / kosong (seperti string kosong atau array / set kosong) Anda dapat menggunakan yang berikut ini:

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
Ini sebenarnya tidak memeriksa objek == [NSNull null] yang mungkin masuk akal.
Peter N Lewis

3

Ada dua situasi:

Ada kemungkinan bahwa suatu objek adalah [NSNull null], atau tidak mungkin.
Aplikasi Anda biasanya tidak boleh menggunakan [NSNull null];Anda hanya menggunakannya jika Anda ingin meletakkan objek " null " ke dalam array, atau menggunakannya sebagai nilai kamus. Dan kemudian Anda harus tahu array atau kamus mana yang mungkin berisi nilai nol, dan yang mungkin tidak.
Jika Anda berpikir bahwa sebuah array tidak pernah mengandung [NSNull null]nilai, maka jangan memeriksanya. Jika ada[NSNull null] , Anda mungkin mendapatkan pengecualian tetapi tidak apa-apa: Pengecualian Objective-C menunjukkan kesalahan pemrograman. Dan Anda memiliki kesalahan pemrograman yang perlu diperbaiki dengan mengubah beberapa kode.

Jika suatu benda bisa menjadi [NSNull null], maka Anda memeriksa ini cukup hanya dengan pengujian
(object == [NSNull null]). Memanggil isEqualatau memeriksa kelas objek tidak masuk akal. Hanya ada satu [NSNull null]objek, dan operator C tua biasa memeriksa untuk itu baik-baik saja dengan cara yang paling mudah dan paling efisien.

Jika Anda memeriksa NSStringobjek yang tidak bisa [NSNull null](karena Anda tahu itu tidak bisa [NSNull null]atau karena Anda baru saja mengeceknya berbeda [NSNull null], maka Anda perlu bertanya pada diri sendiri bagaimana Anda ingin memperlakukan string kosong, yaitu satu dengan panjang 0. Jika Anda memperlakukannya adalah nullstring seperti nil, kemudian tes (object.length == 0). object.length akan mengembalikan 0 jika object == nil, jadi tes ini mencakup objek dan string nil dengan panjang 0. Jika Anda memperlakukan string dengan panjang 0 berbeda dari string nil, cukup periksa apakah object == nil.

Terakhir, jika Anda ingin menambahkan string ke array atau kamus, dan string tersebut bisa nol, Anda memiliki pilihan untuk tidak menambahkannya, menggantinya @"", atau menggantinya dengan [NSNull null]. Menggantinya dengan @""berarti Anda kehilangan kemampuan untuk membedakan antara "tanpa string" dan "string dengan panjang 0". Menggantinya dengan [NSNull null]berarti Anda harus menulis kode ketika Anda mengakses array atau kamus yang memeriksa [NSNull null]objek.


Sangat panjang, tapi ini bagus. NSNull HANYA HARUS MUNCUL DI TUNGGAL! Seluruh pertanyaan ini tidak masuk akal, mengatakan kepada saya bahwa pembuat kode tidak melakukan sesuatu yang benar, dan banyak lagi di masa depan juga, tidak membaca manual / praktik kode yang baik
Stephen J

2

Anda baru saja memeriksa nol

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

atau

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

2

Solusi MACRO (2020)

Berikut ini adalah makro yang saya gunakan untuk string aman daripada mendapatkan string " (null) " pada UILabel misalnya:

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

katakanlah Anda memiliki kelas anggota dan properti nama, dan nama adalah nihil:

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

dengan makro:

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

bagus dan bersih 😊

Solusi Ekstensi (2020)

Jika Anda lebih suka memeriksa nihil Null dan string kosong di proyek Anda, Anda dapat menggunakan baris ekstensi saya di bawah ini:

NSString + Extension.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 + Extension.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;
}

Contoh Penggunaan

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");
}

Ini akan bekerja dengan kasus-kasus berikut, NSString *strOne = @""ATAU NSString *strOne = @"StackOverflow"ATAU NSString *strOne = [NSNull null]ATAU NSString *strOne.


0

Jika hal semacam itu belum ada, Anda dapat membuat kategori NSString:

@interface NSString (TrucBiduleChoseAdditions)

- (BOOL)isEmpty;

@end

@implementation NSString (TrucBiduleChoseAdditions)

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

@end

Itu mungkin berlebihan dan saya pikir itu tidak akan menyelesaikan masalah ini.
Rog,

9
Self == nil tidak ada gunanya - jika self nil, Objective C tidak akan memanggil Anda sejak awal. [(NSString *) nil isEmpty] cukup mengembalikan 0 / nil / false tanpa pernah memanggil kode Anda.
Peter N Lewis

4
Sebenarnya, lebih jauh dari itu, [(NSString *) nil isEmpty] akan mengembalikan false. Saat menulis metode Objective C seperti itu, lebih baik untuk mendefinisikannya sehingga 0 / nil / false nil masuk akal, jadi menulis metode sebagai hasCharacters akan lebih baik. Perhatikan bahwa panjang sudah bekerja untuk ini, karena Anda dapat menggunakan if (s.length) di mana pun Anda ingin menggunakan if (! S.isEmpty) dan s.length akan mengembalikan 0 untuk case s == nil.
Peter N Lewis

Ini kecelakaan serius. Anda menerapkan "isEmpty" untuk NSString, tetapi jika itu sebenarnya NSNull, maka isEmpty akan dikirim ke NSNull, dan macet karena tidak menanggapi pesan itu!
daniel.gindi

0

Yang berhasil bagi saya adalah if ( !myobject )


3
Itu tidak bekerja untuk objek nol, hanya objek nihil. Misalnya ... 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 .. maaf tentang format, tetapi kode akan dikompilasi :)
Rik Smith-Unna

0

Pemeriksaan lengkap string untuk kondisi nol dapat sebagai berikut: <\ br>

    jika (mystring)
     {
       if ([mystring isEqualToString: @ ""])
        {
          mystring = @ "some string";
        }
     }    
    lain
     {
        // pernyataan
     }

0

Saya hanya memeriksa string nol dengan

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


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

1
Meskipun potongan kode ini dapat menjawab pertanyaan, namun tidak memberikan konteks apa pun untuk menjelaskan bagaimana atau mengapa. Pertimbangkan untuk menambahkan satu atau dua kalimat untuk menjelaskan jawaban Anda.
naskah merek

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

0

Untuk string:

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

}

Lihat gambar di bawah ini:

masukkan deskripsi gambar di sini


0

Untuk string:

+ (BOOL) checkStringIsNotEmpty:(NSString*)string {
if (string == nil || string.length == 0) return NO;
return YES;}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.