iOS基礎總結一(UIKit、Foundation)

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

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

實現方案:

  1. 線程鎖:使用線程鎖對數組的讀寫操作進行加鎖;
  2. 派發隊列:使用“串行同步隊列”(serial synchronization queue),將讀取操作及寫入操作都安排在同一個隊列裏,即可保證數據同步。而通過併發隊列,結合GCD的柵欄塊(barrier)來不僅實現數據同步線程安全,還比串行同步隊列方式更高效。

2.id和instanceType有什麼區別

相同點:instanceType 和id 都是萬能指針,指向任意對象;

不同點:1.id在編譯時不能判斷對象的真實類型,instanceType在編譯的時候,可以判斷對象的真實類型;2.id可以用來定義變量,可以作爲返回值類型,可以作爲行參類型,instanceType只能作爲返回值類型。

3.setNeedsDisplay和layoutIfNeeded兩者有什麼關係?

UIView的setNeedsDisplay和setNeedsLayout兩個方法都是異步執行的。而setNeedsDisplay會自動調用drawrect方法,這樣可以拿到UIGraphicsGetCurrentContext進行繪製;而setNeedsLayout會默認調用layoutSubviews,給當前的視圖做了標記;layoutfNeeded查找是否有標記,如果有標記會立即刷新。

只有setNeedsLayout和layoutIfNeeded這二者結合起來使用,纔會起到立即刷新的效果。

4.@property的本質是什麼?ivar、getter、setter是如何生成並添加到類中的?

  • @property的本質是實例變量(ivar)+存取方法(getter、setter),即@property = ivar+ getter + setter;

     "屬性"(property)作爲OC的一項特性,主要作用在於封裝對象中的數據。OC對象通常會把期所需要的書就保存爲各種實例變量。實例變量一般通過存取方法來訪問,其中,getter方法用於讀取變量值,setter方法用戶寫入變量值。

  • ivar、getter、setter是自動合成到類中的。

完成屬性定義後,編譯器會自動編寫訪問這些屬性所需要的方法,這個過程叫做“自動合成”。需要強調的是,這個過程由編譯器在編譯期完成,所以你編輯器裏面看不到這些合成源代碼。除了生成方法代碼getter、setter之外,編譯器還要自動向類中添加適當類型的實例變量,並在屬性名前加上下劃線_,以此作爲實例變量的名字。也可以在類的實現代碼裏通過@synthesize語法來指定實例變量的名字。

5.iOS內存分區情況

  • 棧區(Stack):

由編譯器自動分配和釋放,存放函數的參數、局部變量的值等;棧是向低地址擴展的數據結構,是一塊連續的存儲區域

  • 堆區(Heap):

由程序員分配和釋放,是向高地址擴展的數據結構,是一個不連續的內存區域。

  • 全局區:

全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量是在一塊區域,未初始化的全局變量和靜態變量是在相鄰 的另一塊區域。

  • 常量區:

存放常量字符串,程序結束後由系統釋放。

  • 代碼區:

存放函數體的二進制代碼

  • 注:

(1)在 iOS中,堆區的內存是應用程序共享的,堆中的內存分配是由系統負責的。

(2)系統使用一個鏈表來爲維護所有已經分配的內存空間(系統僅僅記錄,比ing不管理具體的內容)

(3)變量使用結束後,需要釋放內存,OC中判斷引用計數是否爲0,如果是0就說明沒有任何變量使用該空間,那麼系統將其回收。

(4)當一個APP啓動後,代碼區、常量區、全局區的大小就已經固定,因此指向這些區的指針不會產生崩潰性錯誤。而堆區和棧區是時刻變化的(堆的創建銷燬,棧的入棧出棧),所以當一個指針指向這個區裏的內存時,一定要注意內存是否已經被釋放,否則會產生程序崩潰(野指針)。

 

 

 

 

 

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