原創(chuàng)文章轉(zhuǎn)載請注明出處,謝謝
關(guān)于OC中的nil, NULL詳解
我相信很多同學(xué)對于這四種表示空的方式肯定不會(huì)陌生了,網(wǎng)上也有不少介紹四種方式區(qū)別的囚衔,不過我還是想說一些自己的理解框往。
關(guān)于nil
nil的定義是null pointer to object-c object,指的是一個(gè)OC對象指針為空冶匹,本質(zhì)就是(id)0,是OC對象的字面0值
不過這里有必要提一點(diǎn)就是OC中給空指針發(fā)消息不會(huì)崩潰的語言特性咆瘟,原因是OC的函數(shù)調(diào)用都是通過objc_msgSend進(jìn)行消息發(fā)送來實(shí)現(xiàn)的嚼隘,相對于C和C++來說,對于空指針的操作會(huì)引起Crash的問題袒餐,而objc_msgSend會(huì)通過判斷self來決定是否發(fā)送消息飞蛹,如果self為nil,那么selector也會(huì)為空灸眼,直接返回卧檐,所以不會(huì)出現(xiàn)問題。
這里補(bǔ)充一點(diǎn)焰宣,如果一個(gè)對象已經(jīng)被釋放了霉囚,那么這個(gè)時(shí)候再去調(diào)用方法肯定是會(huì)Crash的,因?yàn)檫@個(gè)時(shí)候這個(gè)對象就是一個(gè)野指針了匕积,安全的做法是釋放后將對象重新置為nil盈罐,使它成為一個(gè)空指針,大家可以在關(guān)閉ARC后手動(dòng)release對象驗(yàn)證一下闪唆。(2016.05.24補(bǔ))
NSString *name = @"Allen";
if (name != nil && [name isEqualToString:@"Allen"]) {
NSLog(@"name: %@", name);
} else {
NSLog(@"name is nil");
}
//or
if ([name isEqualToString:@"Allen"]) {
NSLog(@"name: %@", name);
} else {
NSLog(@"name is nil");
}
上面的兩種判斷都是正確的暖呕,我們不必?fù)?dān)心當(dāng)name為nil時(shí)調(diào)用isEqualToString會(huì)出現(xiàn)Crash,但是我還是想說苞氮,在使用一個(gè)對象之前判斷它是否為nil是一個(gè)很好的習(xí)慣湾揽,個(gè)人覺得有兩個(gè)原因:
-
降低時(shí)間復(fù)雜度(感覺可以這么說吧),如果你增加了nil的判斷笼吟,那么不需要對空指針發(fā)送消息了库物,發(fā)消息其實(shí)是件費(fèi)時(shí)的操作。
詳情可以看這里 把判斷為空養(yǎng)成習(xí)慣其實(shí)是好事贷帮,這樣在你切換語言時(shí)也不容易出錯(cuò)戚揭。
關(guān)于NULL
*NULL的定義是null pointer to primitive type or absence of data,指的是一般的基礎(chǔ)數(shù)據(jù)類型為空撵枢,可以給任意的指針賦值民晒。本質(zhì)就是(void )0精居,是C指針的字面0值。
NSInteger *pointerA = NULL;
NSInteger pointerB = 10;
pointerA = &pointerB;
NSLog(@"%ld", *pointerA);
我們要盡量不去將NULL初始化OC對象潜必,可能會(huì)產(chǎn)生一些異常的錯(cuò)誤靴姿,要使用nil,NULL主要針對基礎(chǔ)數(shù)據(jù)類型磁滚。
關(guān)于Nil
Nil的定義是null pointer to object-c class佛吓,指的是一個(gè)類指針為空。本質(zhì)就是(class)0垂攘,OC類的字面零值维雇。
Class class = [NSString class];
if (class != Nil) {
NSLog(@"class name: %@", class);
}
關(guān)于NSNull
NSNull好像沒有什么具體的定義(懵),它包含了唯一一個(gè)方法+(NSNull)null晒他,[NSNull null]是一個(gè)對象吱型,用來表示零值的單獨(dú)的對象。*
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
NSString *nameOne = @"Allen";
NSString *nameTwo = [NSNull null]; //not use nil
NSString *nameThree = @"Tom";
[dictionary setObject:nameOne forKey:@"nameOne"];
[dictionary setObject:nameTwo forKey:@"nameTwo"];
[dictionary setObject:nameThree forKey:@"nameThree"];
NSLog(@"names: %@", dictionary);
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:nameOne];
[array addObject:nameTwo];
[array addObject:nameThree];
NSLog(@"names : %@", array);
NSNull主要用在不能使用nil的場景下陨仅,比如NSMutableArray是以nil作為數(shù)組結(jié)尾判斷的津滞,所以如果想插入一個(gè)空的對象就不能使用nil,NSMutableDictionary也是類似掂名,我們不能使用nil作為一個(gè)object,而要使用NSNull
總結(jié)
其實(shí)這幾種空類型還是很好理解的哟沫,重要的是我們需要在平時(shí)的項(xiàng)目中也切實(shí)運(yùn)用起來饺蔑,不小心初始化的錯(cuò)誤可能導(dǎo)致一些難以發(fā)現(xiàn)的Bug。