iOS 面試第三節 Foundation框架

所有的Mac OS X和IOS程序都是由大量的對象構成,而這些對象的根對象都是NSObject,NSObject就處在Foundation框架之中
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

1.nil、NIL、NSNULL 、NULL有什麼區別?

  1. nil、NIL可以說是等價的,都代表內存中一塊空地址。
  2. NSNull代表一個指向nil的對象。
  3. Null是指針爲空

{1} 對象賦值的時候 Object = nil; 表示我想把這個對象釋放掉。或者經過某些原因,經多次release,引用計數爲0,導致系統將這塊內存釋放掉,這個時候這個對象爲nil,我稱它爲“空對象”。(注意:我這裏強調的是“空對象”,下面我會拿它和“值爲空的對象”作對比!!!)。對於這種”空對象“,所有關於retain的操作都會導致程序crash,例如可變數組添加此對象、字典中添加此對象都會本崩潰,但是調用此對象方法、查看此對象的屬性是不會崩潰的,只是無法執行。個人理解爲可以拿到這個PersonTest 類型的虛擬的實例,所以可以對這個虛擬的實例進行屬性,方法調用只是不會奏效,但是由於內存中沒有這個虛擬實例的內存所以涉及有關retain的內存管理時候,就會引起crash.

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    NSMutableArray *mutableArr = [NSMutableArray array];
    PersonTest *people = nil;
    people.name = @"小明";
    [people testGoMeth]; //此處不崩潰
    [mutableArr addObject:people];// 只有此處崩潰
}

{2}NSNull和nil的區別在於,nil是一個"空對象”,已經完全從內存中消失了,而如果我們想表達“我們需要有這樣一個容器,但這個容器裏什麼也沒有”的觀念時,我們就用到NSNull,我稱它爲“值爲空的對象”。如果你查閱開發文檔你會發現NSNull這個類是繼承NSObject,並且只有一個“+ (NSNull *) null;”類方法。這就說明NSNull對象擁有一個有效的內存地址,所以在程序中對它的retain引用都是不會導致程序崩潰的,但如果對這個實例裏面屬性、方法進行調用賦值是不可以的。個人理解爲:指針指向的空間是存在一個實例對象,但是這個實例對象是空的,雖然實例對象類型還是PersonTest,但由於是一個對象值爲空,所以不能對其進行讀取,方法調用了。但是作爲一個存在的空對象也是有內存的,所以是可以進行retain操作的。 參考代碼如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    NSMutableArray *mutableArr = [NSMutableArray array];
    PersonTest *people = [NSNull null];
    people.name = @"小明";// 此處crash
    [people testGoMeth]; //此處crash
    [mutableArr addObject:people];// 此處不崩潰
}

{3}Nil
nil和Nil在使用上是沒有嚴格限定的,也就是說凡是使用nil的地方都可以用Nil來代替,反之亦然。只不過從編程人員的規約中我們約定俗成地將nil表示一個空對象,Nil表示一個空類。

{4}我們知道Object-C來源於C、支持於C,當然也有別於C。而NULL就是典型C語言的語法,它表示一個空指針,參考代碼如下:
int *ponit = NULL;

理解這個的時候需要首先搞明白什麼是指針?
通俗點兒理解其實它就是就是一個存放地址的變量存儲空間,當指針指向某個變量,這時這個指針裏就存放了那個變量的地址。這就是我們常說的指針指向一個地址,意思是通過它能找到以它爲地址的內存單元。利用指針我們可以直接獲取變量中的值用,要是在指針前加 * 就是取其真值了(也就是被指向的變量的值)

舉個例子:
如果一個整型變量int i,int* p=&i表示將 i 的地址存入整型指針變量即int*中 。

&i表示對i 取地址,返回值是i的地址。

假設i在內存中所存在的地址爲xx0bd00a(隨便寫的)

也就是說 指針p中存放了xx0bd00a這個地址

當你操作這個p時就是直接操作了xx0bd00a這個地址中存放的東西,間接操作了變量i,這就是指針的作用。

那我們在看看內存是什麼(其實上面已經描述很清楚了)?內存是實實在在的硬件,可以存放數據,地址是內存的標識,每一個地址都對應一個內存。所以內存和地址是一一對應密不可分的。
比如說內存就像一個個的小格子,每個格子的大小是一個字節,可以存放一個字節的數據,而指針地址呢,就是存放盒子標號的,我們得到指針,也就可以找到那個盒子了(當然也存在找不到的情況,那就是野指針和空指針,這裏就不詳細敘說了)。

野指針就是內存中變量搬家了,或者被系統釋放了,從而導致你當前指針中取的這個地址找不到它了。

空指針就是這個指針的值爲空Null。

2.如何實現一個線程安全的 NSMutableArray?

NSMutableArray是線程不安全的,當有多個線程同時對數組進行操作的時候可能導致崩潰或數據錯誤

  • 線程鎖:使用線程鎖對數組讀寫時進行加鎖
    但是並不推薦這麼做,對數組的讀寫都加鎖,雖然數組是線程安全了,但失去了多線程的優勢

  • 派發隊列:在《Effective Objective-C 2.0…》書中第41條:多用派發隊列,少用同步鎖中指出:使用“串行同步隊列”(serial synchronization queue),將讀取操作及寫入操作都安排在同一個隊列裏,即可保證數據同步。而通過併發隊列,結合GCD的柵欄塊(barrier)來不僅實現數據同步線程安全,還比串行同步隊列方式更高效。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章