原創(chuàng)文章轉(zhuǎn)載請注明出處,謝謝
關于OC中的nil, NULL詳解
我相信很多同學對于這四種表示空的方式肯定不會陌生了,網(wǎng)上也有不少介紹四種方式區(qū)別的,不過我還是想說一些自己的理解。
關于nil
nil的定義是null pointer to object-c object,指的是一個OC對象指針為空,本質(zhì)就是(id)0,是OC對象的字面0值
不過這里有必要提一點就是OC中給空指針發(fā)消息不會崩潰的語言特性,原因是OC的函數(shù)調(diào)用都是通過objc_msgSend進行消息發(fā)送來實現(xiàn)的,相對于C和C++來說,對于空指針的操作會引起Crash的問題,而objc_msgSend會通過判斷self來決定是否發(fā)送消息,如果self為nil,那么selector也會為空,直接返回,所以不會出現(xiàn)問題。
這里補充一點,如果一個對象已經(jīng)被釋放了,那么這個時候再去調(diào)用方法肯定是會Crash的,因為這個時候這個對象就是一個野指針了,安全的做法是釋放后將對象重新置為nil,使它成為一個空指針,大家可以在關閉ARC后手動release對象驗證一下。(2016.05.24補)
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");
}
上面的兩種判斷都是正確的,我們不必擔心當name為nil時調(diào)用isEqualToString會出現(xiàn)Crash,但是我還是想說,在使用一個對象之前判斷它是否為nil是一個很好的習慣,個人覺得有兩個原因:
-
降低時間復雜度(感覺可以這么說吧),如果你增加了nil的判斷,那么不需要對空指針發(fā)送消息了,發(fā)消息其實是件費時的操作。詳情可以看這里 把判斷為空養(yǎng)成習慣其實是好事,這樣在你切換語言時也不容易出錯。
關于NULL
*NULL的定義是null pointer to primitive type or absence of data,指的是一般的基礎數(shù)據(jù)類型為空,可以給任意的指針賦值。本質(zhì)就是(void )0,是C指針的字面0值。
NSInteger *pointerA = NULL;
NSInteger pointerB = 10;
pointerA = &pointerB;
NSLog(@"%ld", *pointerA);
我們要盡量不去將NULL初始化OC對象,可能會產(chǎn)生一些異常的錯誤,要使用nil,NULL主要針對基礎數(shù)據(jù)類型。
關于Nil
Nil的定義是null pointer to object-c class,指的是一個類指針為空。本質(zhì)就是(class)0,OC類的字面零值。
Class class = [NSString class];
if (class != Nil) {
NSLog(@"class name: %@", class);
}
關于NSNull
NSNull好像沒有什么具體的定義(懵),它包含了唯一一個方法+(NSNull)null,[NSNull null]是一個對象,用來表示零值的單獨的對象。*
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é)尾判斷的,所以如果想插入一個空的對象就不能使用nil,NSMutableDictionary也是類似,我們不能使用nil作為一個object,而要使用NSNull
總結(jié)
其實這幾種空類型還是很好理解的,重要的是我們需要在平時的項目中也切實運用起來,不小心初始化的錯誤可能導致一些難以發(fā)現(xiàn)的Bug。