Kiedy należy używać nil i NULL w Objective-C?

170

Oto przykładowy kod:

NSDictionary *myDictionary = [NSDictionary dictionary];
NSNumber *myNumber = [myDictionary valueForKey: @"MyNumber"];
NSLog(@"myNumber = %@", myNumber); // output myNumber = (null)

if (myNumber == nil)
    NSLog(@"test 1 myNumber == nil");

if (myNumber == NULL)
    NSLog(@"test 2 myNumber == NULL");

if ([myNumber isEqual:[NSNull null]])
    NSLog(@"test 3 myNumber == [NSNull null]");

Kiedy należy używać nil, NULL i [NSNull null]?

Biranchi
źródło
4
Jest to związane z pytaniem dotyczącym celu C.
Biranchi
niloznacza rodzaj NULLinstancji for objc. Możesz więc oznaczyć określoną wartość, która jest przeznaczona dla instancji objc lub wskaźnika ogólnego. Ze względu na zarządzanie typami i bezpieczeństwo, będzie to bardzo pomocne.
eonil
4
nili null/ NULLsą takie same - oba zdefiniowane jako zero. Jako formalność, używaj nilpodczas kodowania Objective-C i NULLpodczas kodowania zwykłych instrukcji / wywołań C / C ++. NSNulljest jednak czymś zupełnie innym. Jest to obiekt typu singleton, który służy jako symbol zastępczy reprezentujący „nic”, np. W NSDictionarys, w których wskaźniki nil / null nie są dozwolone.
Hot Licks,
Odnośnik do dobrego wyjaśnienia [tutaj] [1] [1]: stackoverflow.com/questions/5908936/…
Ameer
1
możliwy duplikat NULL vs zero w Objective-C
awiebe

Odpowiedzi:

114

Możesz używać nilwszędzie, gdzie możesz użyć null. Główną różnicą jest to, że możesz wysyłać wiadomości do nil, więc możesz go używać w niektórych miejscach, w których nullnie możesz pracować.

Ogólnie po prostu użyj nil.

Alex
źródło
12
technicznie są dokładnie równe, możesz wysyłać wiadomości zarówno do zera, jak i do NULL. Idiomatycznie, chociaż nil jest zwykle używany do reprezentowania obiektu
cobbal
41
również w MacTypes.h jest#define nil NULL
cobbal
8
Tak, jak mówi cobbal, są takie same. Jest to bardziej odniesienie kontekstowe, w którym NULL jest wskaźnikiem do 0x0, nil to nieistniejący obiekt obiektyw-c, a Nil to nieistniejąca klasa obiektywna-c, ale technicznie rzecz biorąc, wszystkie są po prostu 0. Poza tym jest NULL nie null - null jest w Javie lub C #, ale nie w Objective-C.
Jason Coco
16
Ta zaakceptowana odpowiedź nie uwzględnia faktu, że [NSNull null]jest to zupełnie inna bestia. Cytując z NSNull Class Reference : „Klasa NSNull definiuje pojedynczy obiekt używany do reprezentowania wartości null w obiektach kolekcji (które nie zezwalają na wartości zerowe)”. Zobacz również sekcję Używanie NSNull w tematach programowania liczb i wartości.
Rob
„Główna różnica polega na tym, że możesz wysyłać wiadomości do zera” - możesz również wysyłać wiadomości do NULL.
313

Różnią się typami. Wszystkie mają wartość zero, ale NULLjest a void *, niljest idi Niljest wskaźnikiem klasy.

NSResponder
źródło
14
Najlepsze wyjaśnienie, jakie słyszałem o różnicy (: Dzięki.
Jacob
3
Powinna to być akceptowana odpowiedź, nie dlatego, że jest więcej głosów pozytywnych, ale dlatego, że ma najlepsze wyjaśnienie postawionego pytania.
James Mertz,
5
Elegancki opis NULLv nil, ale to poważnie pomija znak re [NSNull null]. Zobacz sekcję Using NSNull w Number and Value Programming Topics i NSNull Class Reference .
Rob
Oba wydają się być wskazówkami void *. Inna odpowiedź tutaj już o tym wspomina, ale jeśli się zagłębisz objc.h, znajdziesz linię #define nill __DARWIN_NULL.
gkb0986,
1
Ta odpowiedź brzmi dobrze, ale według innych odpowiedzi jest po prostu niepoprawna.
n13
30

nil jest pustą wartością powiązaną / odpowiadającą obiektowi (typ id w Objective-C). nil nie ma odniesienia / adresu, tylko pustą wartość.

NSString *str = nil;

Więc nil powinno być używane, jeśli mamy do czynienia z przedmiotem.

if(str==nil)
    NSLog("str is empty");

Teraz NULL jest używany dla wskaźnika niebędącego przedmiotem (jak wskaźnik C) w Objective-C. Podobnie jak nil , NULL nie ma wartości ani adresu.

char *myChar = NULL;
struct MyStruct *dStruct = NULL;

Jeśli więc zaistnieje sytuacja, w której muszę sprawdzić, czy moja struct (zmienna typu struktury) jest pusta, czy nie, to użyję:

if (dStruct == NULL)
    NSLog("The struct is empty");

Spójrzmy na inny przykład

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

W przypadku obserwacji klucz-wartość kontekst powinien być wskaźnikiem C lub odwołaniem do obiektu. Tutaj dla kontekstu nie możemy użyć nil ; musimy użyć NULL .

Wreszcie klasa NSNull definiuje pojedynczy obiekt używany do reprezentowania wartości null w obiektach kolekcji (NSArray, NSDictionary). [NSNull null] will powraca instancja pojedyncza z NSNull. Zasadniczo [NSNull null] jest właściwym obiektem.

Nie ma możliwości wstawienia obiektu zerowego do obiektu typu kolekcji. Spójrzmy na przykład:

NSMutableArray *check = [[NSMutableArray alloc] init];
[check addObject:[NSNull null]];
[check addObject:nil];

W drugiej linii nie otrzymamy żadnego błędu, ponieważ wstawienie obiektu NSNull do obiektu typu kolekcji jest całkowicie uczciwe. W trzecim wierszu pojawi się błąd „obiekt nie może być zerowy”. Ponieważ zero nie jest przedmiotem.

Shad
źródło
+1 za wzmiankę o praktycznym użyciu nil / null w tablicy.
Michael
19

NULL i nil są sobie równe, ale nil jest wartością obiektu, podczas gdy NULL jest ogólną wartością wskaźnika ( (void*)0konkretnie). [NSNull null]jest obiektem, który ma zastępować zero w sytuacjach, gdy zero jest niedozwolone. Na przykład nie możesz mieć wartości zerowej w tablicy NSArray. Więc jeśli chcesz przedstawić „zero”, możesz użyć [NSNull null].

Chuck
źródło
12

Znalazłem następujące:

objc.h

#define Nil __DARWIN_NULL   /* id of Nil class */
#define nil __DARWIN_NULL   /* id of Nil instance */

_types.h

#define __DARWIN_NULL ((void *)0)

stddef.h

#undef NULL
#ifdef __cplusplus
#undef __null  // VC++ hack.
#define NULL __null
#else
#define NULL ((void*)0)
#endif

MacTypes.h

#ifndef NULL
#define NULL    __DARWIN_NULL
#endif /* ! NULL */
#ifndef nil
    #define nil NULL
#endif /* ! nil */

Wygląda na to, że nie ma różnicy, ale koncepcyjna.

Colnaghi
źródło
8

Uważaj, że if([NSNull null])powraca true.

Nicolas Manzini
źródło
7

Oba są po prostu zerami typu typecast. Funkcjonalnie nie ma między nimi różnicy. to znaczy.,

#define NULL ((void*)0)
#define nil ((id)0)

Jest różnica, ale kompilator nie przejmuje się tylko Tobą i innymi ludźmi, którzy czytają kod.

Jeszcze jedno zero to wartość obiektu, podczas gdy NULL to ogólna wartość wskaźnika.

Nirav
źródło
6

W nowoczesnych pakietach SDK dla systemów OS X i iOS:

  • nili Nila NULLsą takie same w celu C w celu C ++, po czym c ++ 11.
  • nili Nila std::nullptrsą takie same w celu C ++ z C ++ 11.

Stylistycznie, wiele osób woli używać nildla obiektów Objective-C i / NULLlub nullptrdla innych typów wskaźników. Ja sam teraz używam nilwszędzie.

[NSNull null]jest pojedynczym obiektem używanym do reprezentowania wartości null w sytuacjach, w których niljest zabronione jako wartość (zwykle w obiekcie kolekcji, takim jak NSArraylub NSDictionary). Tematy programowania liczb i wartości: Korzystanie z NSNull

Greg Parker
źródło
5

Aby rozwinąć komentarz z @cobbal:

MacTypes.h zawiera:

#ifndef nil
   #define nil NULL
#endif
Justin Tanner
źródło
4

Jak już wspomniano, są takie same, ale używam jednego lub drugiego w zależności od języka, w którym napisano odpowiedni framework.

Do wszystkiego, co dotyczy Objective-C, używam nil. Na przykład:

- (BOOL)doSomethingWithObjectsInArray:(NSArray *)anArray {
    if (anArray == nil) return NO;

    // process elements
    ...
}

Jednak podczas sprawdzania poprawności modeli danych z frameworka C (takiego jak Framework AddressBook i CoreFoundation) używam NULL. Na przykład:

- (BOOL)showABUnknownPersonVCForABRecordRef:(ABRecordRef)aRecord {
    if (aRecord == NULL) return NO;

    // set-up the ABUnknownPersonViewController and display it on screen
    ..
}

W ten sposób mam subtelne wskazówki w moim kodzie, jeśli mam do czynienia z kodem opartym na Obj-C lub C.

Tafkadasoh
źródło
4

nil jest wskaźnikiem obiektu do niczego. Chociaż semantycznie różnią się od NULL , są one technicznie równoważne .

Na poziomie platformy Foundation definiuje NSNull , który definiuje metodę klasy + null, która zwraca pojedynczy obiekt NSNull. NSNull różni się od nil lub NULL tym , że jest rzeczywistym obiektem , a nie wartością zerową.

Ponadto w Foundation / NSObjCRuntime.h Nil jest zdefiniowane jako wskaźnik klasy do niczego.

Więcej informacji znajdziesz w tym artykule - nil / Nil / NULL / NSNull

Shubham Jain
źródło
3

W niektórych kontekstach występuje różnica.

Dosłownie Null to znak: ASCII 0.

Brak jest równoznaczne z pustą wartością, brak wartości.

W zależności od kontekstu programowania może to być duża różnica.

Meatloaf
źródło
1

Użyj wartości NULL, na przykład, gdy wywołujesz metodę Objective-C z parametrem wyjściowym typu (NSError **).

Widzę wiele przykładowych kodów w sieci, w których ludzie w tym przypadku podają nil zamiast NULL. Dzieje się tak, ponieważ jest to wskaźnik do wskaźnika, a zatem nie jest bezpośrednio typem obiektu Objective-C. Jak wspomniano powyżej, nil powinno być używane dla typów obiektów Objective-C.

Peter Mortensen
źródło
1

Zasadniczo: nil: null wskaźnik na obiekcie i null: jest dla innego wskaźnika typu

gerachev
źródło
0

zero oznacza brak wartości, podczas gdy NULL oznacza brak obiektu,

NSArray * array = @ [@ "Hello World!", @ 101, [NSNULL null]];

Tutaj [NSNULL null] jest obiektem, co oznacza brak obiektu, w tym samym czasie nie można dodać nil, aby wskazać brak obiektu.

możesz użyć zarówno nil, jak i [NSNUll null] do sprawdzania.

Roshan Sah
źródło
0

Pomoże ci to zrozumieć różnicę między nil, NIL i null.

Poniższy link może w jakiś sposób pomóc:

http://nshipster.com/nil/

nil -> literalna wartość null dla obiektów Objective-C.

Nil -> dosłowna wartość null dla klas celu-C.

NULL -> literalna wartość null dla wskaźników C.

NSNULL -> pojedynczy obiekt używany do reprezentowania wartości null.

Subhakar Prabhu
źródło
czy to dodaje coś nowego (czego nie obejmują istniejące odpowiedzi)?
Florian Koch,