聊聊iOS面試的那些事

編程語言 iOS Objective-C Arc 小手西語學習 2017-04-05

筆試面試是程序員應聘繞不過的坎,想進大廠就一定要有知識儲備量,而這個卻是最佳的考察方式。筆者分享一些收集的iOS面試題,答案僅供參考,如有錯誤,還請指正。

第一部分

1.Objective-C語言的基本特點?

Objective-C語言是C語言的一個超集,只是在C的基礎之上添加了面向對象(OO)的特性;Objective-C與Java語言相同都是單繼承,這一點與C++語言不同(多重繼承),這一點可以參看之前有關講解繼承的文章;Objective-C不支持命名空間,取而代之的是在類名之前添加前綴,以此來區分。

2.#include與#import的區別,#import與@class的區別?

1)#include和#import效果相同,只是後者不會引起交叉編譯,確保頭文件只會被導入一次。

2)#import會包含這個類的所有信息,包括實體變量和方法,而@class只是告訴編譯器,其後面聲明的名稱是類的名稱,至於這些類是如何定義的,暫時不用考慮,後面會再告訴你。使用#import編譯效率高,防止相互包含的編譯錯誤。

3.簡述類目優缺點,如果覆蓋本類或者父類的方法會出現什麼問題?

優點:不需要通過增加子類而增加現有類的行為(方法),且類目中的方法與原始類方法基本沒有區別。

缺點:無法向類目添加實例變量。覆蓋原始類方法後,原始類的方法沒辦法調用。

4.簡述內存管理基本原則?

如果使用alloc、copy(mutableCopy)或者retain一個對象時,你就有義務向它發送一條release或autorelease消息。其他方法創建的對象,不需要由你來管理內存。

5.什麼是ARC技術?與GC是否相同?

ARC是Automatic Reference Counting的簡稱,我們稱之為自動引用計數,是iOS5.0之後推出的內存管理的新特性。本質上還是使用引用計數來管理對象,只是我們在編寫代碼時,不需要向對象發送release或autorelease方法,也不可以調用dealloc方法,編譯器會在合適的位置自動給用戶生成release(autorelease)消息。GC是Garbage Collection,內存垃圾回收機制,ARC比GC性能好。

6.iOS中是否支持垃圾回收機制?

iOS開發只支持MRC與ARC,Mac開發支持GC垃圾回收機制,10.8之後棄用了GC,推薦使用ARC。

7.深、淺複製的基本概念以及區別?

淺複製:只複製對象本身,不對裡面的屬性複製。

深複製:不僅複製對象本身,對象持有的屬性對象也做複製。

8.內存中的堆區和棧區的差別?

棧區(stack)由編譯器自動分配釋放,存放方法(函數)的參數值,局部變量的值等。

堆區(heap)一般由程序員分配與釋放,若程序員不釋放,則會內存溢出。

9.用戶自定義了一個對象,如何實現拷貝(可變和不可變拷貝)?

必須實現copying和mutableCopying協議,表示返回一個不可變和可變的對象。否則,程序將會出現異常。

-(id)copyWithZone:(NSZone *)zone {

10.定義屬性時,什麼時候用assign、retain、copy和nonatomic?

assign:普通賦值,一般常用於基本數據類型,常見委託設計模式,以此來防止循環引用。

retain:保留計數,獲得了對象的所有權。引用計數在原有基礎上加1。

copy:用來複制對象,一般字符串使用,Foundation中的不可變對象使用,效果相當於retain,只是引用計數加1。

nonatomic:非原子性訪問,不加同步,多線程併發訪問會提高性能。

11.strong和weak,_unsafe_unretained與weak的區別?

strong:強引用,在ARC中告訴編譯器幫助我們自動插入retain。

weak:弱引用,是普通賦值,相當於手動管理內存的assign。

_unsafe_unretained:與weak功能一致,區別在於當指向的對象銷燬後,weak會將變量置為nil,防止調用野指針。

12.ARC存在內存洩露嗎?

ARC中如果內存管理不當的話,同樣會存在內存洩露。例如,ARC中也會循環引用導致內存洩露;Objective-C對象與CoreFoundation類之間橋接時,管理不當也會產生內存洩露。

13.當我們釋放對象時,為什麼需要調用[super dealloc]方法?

子類是繼承自父類,那麼子類中有一些實例變量(對象),是繼承自父類的,因此,我們需要調用父類方法,將父類所擁有的實例進行釋放。

14.自動釋放池是什麼,如何工作?

自動釋放池是NSAutorelease類的一個實例,當向一個對象發送autorelease消息時,該對象會自動入池,待池銷燬時,將會向池中所有對象發送一條release消息,釋放對象。

15.為什麼delegate(代理)屬性都是assign而不是retain的?

防止循環引用,以至對象無法得到正確的釋放。

第二部分

1.iOS開發中數據持久性有哪幾種?

plist文件寫入,對象歸檔,sqlite3數據庫,CoreData。

2.什麼是KVC和KVO?它們之間的關係是什麼?

KVC:鍵值編碼,是一種間接訪問對象實例變量的機制,該機制可以不通過存取方法就可以訪問對象的實例變量。

KVO:鍵值觀察,是一種能使得對象獲取到其他對象屬性變化的通知機制。

實現KVO鍵值觀察模式,被觀察的對象必須使用KVC鍵值編碼來修改它的實例變量,這樣才能被觀察者觀察到。因此,KVC是KVO的基礎或者說KVO的實現是建立在KVC的基礎之上的。

3.簡述常見的設計模式?

單例模式、代理設計、觀察者(通知)、工廠方法、模板方法。

4.內存管理在dealloc方法中用release方法與self.xx=nil哪個好?

使用self.xx=nil更好,因為先調用了release方法,而且還將變量設置為nil,這樣就更安全的釋放對象,防止野指針調用。

5.線程與進程的區別和聯繫?

一般的應用程序是單個進程,也有多進程(Chrome),進程是個靜態的容器,裡面容納了很多個線程,線程是一系列方法的線性執行路徑。

6.Objective-C語言的優缺點?

優點:類目、動態識別、支持C語言、Objective-C與C++可以混編。

缺點:不支持命名空間、不支持運算符重載、不支持多重繼承。

7.代理delegate、通知Notification與block的使用區別?

delegate和block一般是用於兩個對象一對一之間的通信交互,delegate需要定義協議方法,代理對象實現協議方法,並且需要建立代理關係才可以實現通信。block更加簡潔,不需要定義繁瑣的協議方法,但是如果通信事件比較多的話,建議使用delegate。

Notification主要用於一對多情況下通信,而且,通信對象之間不需要建立關係,但是使用通知,代碼可讀性差。

8.控制器ViewController的loadView、viewDidLoad、viewWillApear和viewDidUnload分別是在什麼時候調用?

loadView:當控制器的根視圖view為空,且此view被訪問時調用。

viewDidLoad:loadView調用之後被調用。

viewWillApear:當控制器根視圖view被添加到父視圖上時調用。

viewDidUnload:iOS6.0之前,當內存警告時,先卸載視圖,再調用

viewDidUnload來釋放內存。

9.@synthesize和@dynamic的區別?

@synthesize:系統自動生成getter和setter屬性聲明。

@dynamic:告訴編譯器,屬性的獲取與賦值方法由用戶自己實現,不自動生成。

10.事件響應者鏈的概念?

響應者鏈表示一系列的響應者對象。事件被交由第一響應者對象處理,如果第一響應者不處理,事件被沿著響應者鏈向上傳遞,交給下一個響應者。一般來說,第一響應者是個視圖對象或者其子類對象,當其被觸摸後事件交由它處理,如果它不處理,事件會被傳遞給它的視圖控制器對象(如果存在),然後是它的父視圖對象(如果存在),以此類推,直到頂層視圖。接下來會沿著頂層視圖到窗口(UIWindow對象),再到程序(UIApplication對象)。如果整個過程都沒有響應這個事件,該事件被丟棄。一般情況下,在響應者鏈中只要有對象處理事件,事件就停止傳遞。但有時候可以在視圖的響應方法中根據一些條件判斷來決定是否需要繼續傳遞事件。

11.C語言中的static變量和static函數有什麼作用?

1)表示變量是靜態存儲變量,表示變量存放在靜態存儲區。

2)加在函數前面的時候表示該函數是內部連接,只在本文件中有效,別的文件中不能使用該函數。

12.指針題

1)int a; //一個數值。

13.寫一個NSString類的實現?

+(id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding {

14.Objective-C與C如何混用?Objective-C與C++如何混用?

實現文件的擴展名.m改成.mm即可,但cpp文件必須只能使用C/C++代碼,而且cpp文件include的頭文件中,也不能出現Objective-C的代碼,因為cpp只能寫C++的代碼。

15.Objective-C中有私有方法和私有變量嗎?

使用private修飾的全局變量是私有的變量。

Objective-C在語法上沒有設計私有的方法,不過可以通過延展在實現文件裡定義方法作為私有的方法。但不是真正意義上的私有方法,也是可以調用的,只是外部不可見而已。

第三部分

1.下面關鍵字const有什麼含義?

const int a;

前兩個的作用是一樣的,a是一個常整型數。

第三個意味著a是一個指向常整型數的指針(即整型數是不可修改的,但指針可以)。

第四個意味著a是一個指向整型數的常指針(即指針指向的整型數是可以修改的,但指針是不可修改的)。

2.C語言中extern的作用,extern “C”的作用?

1)extern可以置於變量或者函數前,以標示變量或函數的定義在別的文件中,提示編譯器遇到此變量和函數時在其他模塊中尋找其定義。

2)C++語言在編譯的時候為了解決函數的多態問題,會將函數名和參數聯合起來生成一箇中間的函數名稱,而C語言則不會,因此會造成鏈接時找不到對應函數的情況,此時C函數就需要用extern “C”進行鏈接指定,這告訴編譯器,請保持我的名稱,不要給我生成用於鏈接的中間函數名。

3.Objective-C是如何管理內存的?

Objective-C語言是使用引用計數來管理一個對象的生命週期,當對象被其他“人”使用的時候引用計數加1,不使用時減1,當此對象的引用計數為0時,則對象被系統回收。

4.什麼是動態綁定(多態)?

動態綁定是面向對象特性之一多態的體現,聲明一個變量,在運行的時候可以綁定不同的對象,比如在方法的參數中聲明這樣一個變量UIView *view,運行的時候,我們可以根據不同的應用場景給view變量傳入不同的對象,可以傳遞一個UIButton對象,也可以傳入UIImageView對象。

5.如何理解delegate?

delegate,又稱為委託或代理,它是一種設計模式。delegate主要用於兩個對象之間的通信交互,並且解除兩個通信對象的耦合性,iOS中大量使用了delegate設計,主要用於視圖與使用對象之間的通信交互。

6.block與函數有何異同?block有何優點?

1)block類似於C裡面的函數指針,都可以作為參數進行傳遞,用於回調。但是block的實現可以定義在方法中,函數則不可以。

2)block語法簡潔,可以在方法中定義實現,這樣可以訪問方法中的局部變量,使代碼更加的緊湊,結構化。

7.為什麼標準頭文件都有類似以下的結構?

#ifndef __INCvxWorksh

顯然,頭文件中的編譯宏“#ifndef INCvxWorksh、#define INCvxWorksh、#endif”的作用是防止該頭文件被重複引用。

8.CocoaTouch框架?

UIKit、Foundation、CoreGraphic、CoreAnimation

1)音頻和視頻:Core Audio、OpenAL、Media Library、AV Foundation

2)數據管理:Core Data、SQLite

3)圖形和動畫:Core Animation、OpenGL ES、Quartz 2D、Core Graphic

4)用戶應用:Address Book、Core Location、Map Kit、Store Kit

9.棧結構與隊列的區別?

棧(stack):限定只能在表的一端進行插入和刪除操作的線性表。

隊列(queue):限定只能在表的一端插入和在另一端進行刪除操作的線性表。

1)隊列先進先出,棧先進後出。

2)對插入和刪除操作的“限定”不同。

3)遍歷數據速度不同。隊列遍歷數據的速度要快得多。

10.Objective-C中有無多重繼承?如何實現多重繼承?

Objective-C是沒有多重繼承的。

Cocoa中所有的類都是NSObject的子類,多繼承在這裡是用protocol委託代理來實現的。

面嚮對象語言大部分都是單繼承,例如:Java、C#。

C++支持多繼承。

11.static全局變量與普通的全局變量的區別?局部變量呢?函數呢?

1)static全局變量與普通全局變量的區別:static全局變量只初始化一次,防止在其他文件單元中被引用。

2)static局部變量與普通局部變量的區別:static局部變量只被初始化一次,下一次依據上一次結果值。

3)static函數與普通函數的區別:static函數在內存中只有一份,普通函數在每個被調用中維持一份拷貝。

12.什麼是類目與延展?

類目:為已知的類增加新的方法。

延展:通知在本類的定義裡使用類目來聲明私有方法。

13.Objective-C中的協議和Java中的接口區別?

協議定義的方法,可以設置可選實現和必須實現。

接口則是必須全部實現。

14.在一個對象的方法裡self.name=”object”和name=”object”有什麼不同?

前者調用的是設置器方法,後者是普通賦值。

15.單例設計模式的實現?為什麼使用單例設計?

static File *instance = nil;

為什麼使用單例設計?

1)單例設計是用來限制一個類只能創建一個對象,那麼此對象中的屬性可以存儲全局共享的數據,所有的類都可以訪問、設置此單例對象中的屬性數據。

2)如果一個類創建的時候非常的耗費性能,那麼此類如果能滿足要求,可以設置為單例節約性能。

第四部分

1.層CALayer和UIView的區別是什麼?

兩者最大的區別是,圖層不會直接渲染到屏幕上。UIView是iOS系統中界面元素的基礎,所有的界面元素都是繼承自它,它本身是由CoreAnimation來實現的,它真正繪圖的部分是由一個CALayer類來管理的。UIView本身更像是一個CALayer的管理器。一個UIView上可以有多個CALayer,每個CALayer顯示一種東西,增強UIView的展現能力。

2.什麼是GCD?

GCD是Apple開發的一個多核編程的較新的解決方法。在Mac OS X 10.6雪豹中首次推出,並引入到iOS4.0。GCD是一個替代諸如NSThread等技術的很高效和強大的技術。GCD完全可以處理諸如數據鎖定和資源洩漏等複雜的異步編程問題。

3.TCP/UDP的區別和聯繫?

1)TCP的全稱為傳輸控制協議,這種協議可以提供面向連接的、可靠的、點到點的通信。

2)UDP的全稱為用戶數據報協議,它可以提供非連接的不可靠的點到多點的通信。

3)用TCP還是UDP,需要看程序注重哪一個方面,需要可靠還是快速。

4.Socket連接和Http連接的區別?

Http連接:Http連接就是所謂的短鏈接,即客戶端向服務器發送一次請求,服務器響應後連接即會斷掉。

Socket連接:Socket連接就是所謂的長連接,理論上客戶端和服務器端一旦建立起連接將不會主動斷掉。

5.什麼是TCP連接的三次握手?

第一次握手:客戶端發送SYN包(SYN=j)到服務器,並進入SYN_SEND狀態,等待服務器確認。

第二次握手:服務器收到SYN包,必須確認客戶的SYN(ACK=j+1),同時自己也發送一個SYN包(SYN=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態。

第三次握手:客戶端接收到服務器的SYN+ACK包,向服務器發送確認包ACK(ACK=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。

6.frame和bounds的區別?

frame指的是:該view在父view座標系統中的位置大小(參照點是父視圖的座標系統)。

bounds指的是:該view在本身座標系統中的位置和大小(參照點是本身的座標系統)。

7.如何理解MVC設計模式?

MVC是一種架構設計,M表示數據模型,V表示視圖,C表示控制器。

數據模型:負責存儲、定義、操作數據。

視圖:用來展示數據給用戶,和用戶進行操作交互。

控制器:它是M與V的協調者,控制器獲取數據,將數據交給視圖去展示。

8.控制器的xib是怎麼加載的?

當UIViewController的loadView被調用時,在此方法中,通過NSBundle加載xib,先通過控制器的類名作為xib的文件名加載此xib文件。如果找到此xib文件,則加載為view對象作為控制器的根視圖,如果沒有xib文件,則通過alloc創建一個view對象作為根視圖。

9.控制器如何處理系統內存不足警告?

內存不足時,系統會調用控制器didReceiveMemoryWaring方法通知控制器內存不足。iOS6.0與6.0之前的處理方式不一樣。

1)iOS6.0之前:調用didReceiveMemoryWaring後,將self.view設置為nil,並且再調用viewDidUnload方法,在此方法中我們應該釋放子視圖。

2)iOS6.0之後:調用didReceiveMemoryWaring後,不再調用viewDidUnload方法,則應該在didReceiveMemoryWaring方法中手動將self.view=nil,並且釋放子視圖。

10.iOS中對象間有哪些通信方式?

代理delegate、block、通知和KVO。

11.block在內存管理上的特點?需要注意循環引用,如何解決循環引用?

1)block中使用了局部對象,則會將此對象retain,引用了當前對象的屬性或者方法,則會將當前對象retain。

2)解決循環引用:將當前對象賦值給一個局部變量,並且使用__block關鍵字修飾該局部變量,使用該變量訪問當前對象的屬性和方法。

12.Objective-C中有線程池(線程隊列)嗎?NSOperationQueue是如何管理線程的?

NSOperationQueue是Objective-C的線程池,線程池中可以存放多個線程。

NSOperationQueue可以管理線程的併發數,還可以管理線程間的優先級。

13.timer的間隔週期準嗎?為什麼?怎樣實現一個精準的timer?

定時器timer一般都是準確的,但是當主線程有些時候難免會出現堵塞情況,這樣就有可能導致定時器timer會延遲從而不準確。我們可以開發一個多線程,在此多線程上運行定時器,這樣多線程只運行定時器,不會因堵塞而導致誤差。

14.Http協議的特點?GET與POST的區別?什麼是Https協議?

1)Http協議是短鏈接,都是客戶端主動發送請求,服務器做出響應,服務器響應之後,連接則斷開。

2)GET請求沒有請求體,POST含有請求體,請求參數可以放入請求體中,所以,POST可以提交大量的數據給服務器,更加安全。

3)HTTPS(Secure Hypertext Transfer Protocol)安全超文本傳輸協議,它是一個安全通信通道,它基於HTTP開發,用於在客戶計算機和服務器之間交換信息。它使用安全套接字層(SSL)進行信息交換,簡單來說它是HTTP的安全版。

15.XML數據的解析方式各有什麼不同?JSON解析有哪些框架?

XML數據解析有兩種方式:DOM解析和SAX解析。

DOM解析:必須完成DOM樹的構造,在處理規模較大的XML文檔時就很耗費內存,佔用資源較多。

SAX解析:與DOM不同的是,SAX是用事件驅動模型,解析XML文檔時每遇到一個開始或者結束標籤、屬性或一條指令時,程序就產生一個事件來進行相應的處理。因此,SAX相對於DOM來說更適合操作大的XML文檔。

JSON解析:現在性能比較好的主要是第三方的JSONKit和iOS自帶的JSON解析類,自帶的JSON解析性能是最高的,但是隻能是iOS5之後才可以使用。

第五部分

1.tableView是如何複用的?

如果屏幕上能顯示10個單元格,則tableView只會創建11個單元格,也就是n+1,當滑到第12個單元格時就會複用第1個單元格對象。tableView中有個單元格池的概念,tableView調用協議方法獲取單元格時,先從池子中查找是否有可複用的單元格,如果有則複用,如果沒有則創建一個單元格對象。

2.如何優化tableView的滑動速度?

1)複用單元格。

2)使用不透明的視圖,單元格中儘量少使用動畫。

3)圖片加載使用異步加載,並且設置圖片加載的併發數。

4)滑動時不加載圖片,停止滑動開始加載。

5)文字、圖片可直接drawInRect繪製。

6)如非必要,減少reloadData全部cell,只reloadRowsAtIndexPaths。

7)如果cell是動態行高度,計算出高度後緩存。

8)cell高度固定的話直接用cell.rowHeight設置高度。

3.談談對Runloop的理解?

Run loops是線程相關的基礎框架的一部分。一個run loop就是一個事件處理的循環,用來不停的調度工作以及處理輸入事件。使用run loop的目的是讓你的線程在有工作的時候忙於工作,而沒有工作的時候處於休眠狀態。

4.如何調用drawRect方法與layoutSubView方法?這兩個方法的作用?

通過setNeedsLayout方法異步調用layoutSubView方法。

通過setNeedsDisplay方法異步調用drawRect方法。

drawRect方法用於繪圖,layoutSubView方法用於佈局子視圖。

5.UIView與UIViewController的關係?

每個控制器都有一個根視圖,控制器UIViewController用來管理此視圖的加載和顯示。

6.iOS中有哪些手勢?

輕擊、捏合、平移、輕掃、旋轉和長按。

7.Http和Socket的區別?

Http是客戶端用Http協議進行請求,發送請求時需要封裝http請求頭,並綁定請求的數據,服務器一般有Web服務器配合(當然也非絕對)。Http請求方式為客戶端主動發起請求,服務器才能給響應,一次請求完畢後則斷開連接,以節省資源。服務器不能主動給客戶端響應(除非採用http長連接技術)。iPhone主要使用的類是NSURLConnection。

Socket是客戶端跟服務器直接使用Socket套接字進行連接,並沒有規定連接後斷開,所以客戶端和服務器可以保持連接通道,雙方都可以主動發送數據。一般在遊戲開發或股票開發,這種要求即時性很強並且保持發送數據量比較大的場合使用。主要使用的類是CFSocketRef。

8.storyboard有什麼特點?

storyboard是iOS5新增的特性,是對xib的升級版本,引入了一個容器用於管理多個xib文件,和它們之間的跳轉交互。

優點:不用再為每個控制器創建xib文件;可以使用靜態cell,當cell固定且不多時,使用起來比較方便。

缺點:storyboard單個文件,不利於團隊協作開發。

9.如何打包靜態庫?

新建一個Framework&Library的項目,編譯的時候會將項目中的代碼文件打包成一個.a靜態庫文件。

10.APP發佈的上架流程?

1)在蘋果官網的開發者中心,新建一個APP,填寫此APP相關的一些描述信息。

2)下載安裝發佈證書。

3)選擇發佈證書,使用Archive編譯發佈包。

4)使用Xcode提交發布包。

11.iOS5有哪些新特性?

iCloud、定製UI、storyboard、ARC、CoreImage濾鏡、新增JSON解析類。

12.iOS6有哪些新特性?

UIRefreshControl水滴效果下拉刷新、UICollectionView控件的使用、SLComposeViewController新浪微博控件、PassKit中Passbook、AutoLayout自動佈局。

13、iOS7有哪些新特性?

系統:全新的UI設計與交互;Control Center控制中心;全新的多任務Multitasking;AirDrop共享文件;全新的Safari瀏覽器交互式體驗。

SDK:動態UIKit,新增了UIDynamicItem委託,用來為UIView制定動態行為;新增遊戲引擎Sprite Kit Framework框架,類似於Cocos2D。

14.ARC有什麼特點?

ARC是編譯器特性,iOS5.0新添加的特性,使用ARC開發者不需要再retain、release、autorelease,因為編譯器會在合適的地方自動插入retain、release。

ARC不會因少release而導致內存洩漏,過度使用release導致程序崩潰,

ARC可以產生更簡潔的代碼和更健壯的應用。

15.SVN、Git協作開發,怎麼防止代碼文件衝突?

防止代碼衝突:不要多人同時修改同一個文件。例如,A、B都修改同一個文件,先讓A修改,然後提交到服務器,然後B更新下來,再進行修改。

服務器上的項目文件xcodeproj,僅讓一個人管理提交,其他人只更新。防止此文件產生衝突。

第六部分

1.什麼是ARC?

ARC是automatic reference counting自動引用計數,在程序編譯時自動加入retain/release。在對象被創建時retain count+1,在對象被release時count-1,當count=0時,銷燬對象。程序中加入autoreleasepool對象會由系統自動加上autorelease方法,如果該對象引用計數為0,則銷燬。那麼ARC是為了解決MRC手動管理內存存在的一些而誕生的。

MRC下內存管理的缺點:

1)釋放一個堆內存時,首先要確定指向這個堆空間的指針都被release了。(避免提前釋放)

2)釋放指針指向的堆空間,首先要確定哪些指向同一個堆,這些指針只能釋放一次。(避免釋放多次,造成內存洩露)

3)模塊化操作時,對象可能被多個模塊創建和使用,不能確定最後由誰釋放。

4)多線程操作時,不確定哪個線程最後使用完畢。

雖然ARC給我們編程帶來的很多好多,但也可能出現內存洩露。如下面兩種情況:

1)循環參照:A有個屬性參照B,B有個屬性參照A,如果都是strong參照的話,兩個對象都無法釋放。

2)死循環:如果有個ViewController中有無限循環,也會導致即使ViewController對應的view消失了,ViewController也不能釋放。

2.block一般用哪個關鍵字修飾,為什麼?

block一般使用copy關鍵之進行修飾,block使用copy是從MRC遺留下來的“傳統”,在MRC中,方法內容的block是在棧區的,使用copy可以把它放到堆區。但在ARC中寫不寫都行:編譯器自動對block進行了copy操作。

3.用@property聲明的NSString(或NSArray,NSDictionary)經常

使用copy關鍵字,為什麼?如果改用strong關鍵字,可能造成什麼問題?

用@property聲明 NSString、NSArray、NSDictionary 經常使用copy關鍵字,是因為他們有對應的可變類型:NSMutableString、NSMutableArray、NSMutableDictionary,他們之間可能進行賦值操作,為確保對象中的字符串值不會無意間變動,應該在設置新屬性值時拷貝一份。

如果我們使用是strong,那麼這個屬性就有可能指向一個可變對象,如果這個可變對象在外部被修改了,那麼會影響該屬性。

copy此特質所表達的所屬關係與strong類似。然而設置方法並不保留新值,而是將其“拷貝” (copy)。 當屬性類型為NSString時,經常用此特質來保護其封裝性,因為傳遞給設置方法的新值有可能指向一個NSMutableString類的實例。這個類是NSString的子類,表示一種可修改其值的字符串,此時若是不拷貝字符串,那麼設置完屬性之後,字符串的值就可能會在對象不知情的情況下遭人更改。所以,這時就要拷貝一份“不可變” (immutable)的字符串,確保對象中的字符串值不會無意間變動。只要實現屬性所用的對象是“可變的” (mutable),就應該在設置新屬性值時拷貝一份。

4.runloop、autorelease pool以及線程之間的關係?

每個線程(包含主線程)都有一個Runloop。對於每一個Runloop,系統會隱式創建一個Autorelease pool,這樣所有的release pool會構成一個像callstack一樣的一個棧式結構,在每一個Runloop結束時,當前棧頂的Autorelease pool會被銷燬,這樣這個pool裡的每個Object會被release。

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

“屬性”(property)有兩大概念:ivar(實例變量)、存取方法(access method=getter),即@property = ivar + getter + setter。

例如下面的這個類:

@interface WBTextView :UITextView

類完成屬性的定以後,編譯器會自動編寫訪問這些屬性的方法(自動合成autosynthesis),上述代碼寫出來的類等效與下面的代碼:

@interface WBTextView :UITextView

詳細介紹見: http://blog.csdn.net/jasonjwl/article/details/49427377

6.分別寫一個setter方法用於完成 @property (nonatomic,retain)NSString *name 和 @property (nonatomic,copy) NSString *name ?

retain屬性的setter方法是保留新值並釋放舊值,然後更新實例變量,令其指向新值。順序很重要。假如還未保留新值就先把舊值釋放了,而且兩個值又指向同一個對象,先執行的release操作就可能導致系統將此對象永久回收。

-(void)setName:(NSString *)name{

7.說說assign和weak,_block和 _weak的區別?

assign適用於基本數據類型,weak是適用於NSObject對象,並且是一個弱引用。

assign其實也可以用來修飾對象,那麼為什麼不用它呢?因為被assign修飾的對象在釋放之後,指針的地址還是存在的,也就是說指針並沒有被置為nil。如果在後續內存分配中,剛巧分到了這塊地址,程序就會崩潰掉。而weak修飾的對象在釋放之後,指針地址會被置為nil。

_block 是用來修飾一個變量,這個變量就可以在block中被修改。

_block :使用_block修飾的變量在block代碼塊中會被retain(ARC下,MRC下不會retain)。

_weak:使用_weak修飾的變量不會在block代碼塊中被retain。

8.請說出下面代碼是否有問題,如果有問題請修改?

@autoreleasepool {

內存管理的原則:如果對一個對象使用了alloc、copy、retain,那麼你必須使用相應的release或者autorelease。咋一看,這道題目有alloc,也有autorelease,兩者對應起來,應該沒問題。但autorelease雖然會使引用計數減一,但是它並不是立即減一,它的本質功能只是把對象放到離他最近的自動釋放池裡。當自動釋放池銷燬了,才會向自動釋放池中的每一個對象發送release消息。這道題的問題就在autorelease。因為largeNumber是一個很大的數,autorelease又不能使引用計數立即減一,所以在循環結束前會造成內存溢出的問題。

解決方案如下:

@autoreleasepool {

在循環內部再加一個自動釋放池,這樣就能保證每創建一個對象就能及時釋放。

9.請問下面代碼是否有問題,如有問題請修改?

@autoreleasepool {

這道題跟第8題一樣存在內存洩露問題,

1)內存洩露 ;

2)指向常量區的對象不能release。

指針變量str原本指向一塊開闢的堆區空間,但是經過重新給str賦值,str的指向發生了變化,由原來指向堆區空間,到指向常量區。常量區的變量根本不需要釋放,這就導致了原來開闢的堆區空間沒有釋放,造成內存洩露。

10.什麼情況下使用weak關鍵字,相比assign有什麼不同?什麼情況使用weak關鍵字?

1)在ARC中,在有可能出現循環引用的時候,往往要通過讓其中一端使用weak來解決。比如delegate代理。

2)自身已經對它進行一次強引用,沒有必要再強引用一次,此時也會使用weak,自定義控件屬性一般也使用weak。

不同點:

1)weak此特性表明該屬性定義了一種“非擁有關係”。為這種屬性設置新值時,設置方法既不保留新值,也不釋放舊值。此特性與assign一樣,然而在屬性所指的對象遭到銷燬時,屬性值也會清空。而assign的“設置方法”只會執行鍼對“純量類型” (scalar type,例如 CGFloat 或 NSlnteger 等)的簡單賦值操作。

2)assign可以用非OC對象,而weak必須用於OC對象。

11.內存管理語義(assign、strong、weak等的區別)?

1)assign “設置方法” 只會執行鍼對“純量”的簡單賦值操作。

2)strong 此特性表明該屬性定義了一種“擁有關係”。為這種屬性設置新值時,設置方法會先保留新值,並釋放舊值,然後再將新值設置上去。

3)weak 此特性表明該屬性定義了一種“非擁有關係”。為這種屬性設置新值時,設置方法既不保留新值,也不釋放舊值。此特性同assign類似,然而在屬性所指的對象遭到銷燬時,屬性值也會清空。

4)unsafe_unretained 此特性的語義和assign相同,但是它適用於“對象類型”,該特性表達一種“非擁有關係”,當目標對象遭到銷燬時,屬性值不會自動清空,這一點與weak有區別。

5)copy 此特性所表達的所屬關係與strong類似。然而設置方法並不保留新值,而是將其“拷貝”。當屬性類型為NSString*時,經常用此特性來保護其封裝性,因為傳遞給設置方法的新值有可能指向一個NSMutableString類的實例。這個類是NSString的子類,表示一種可以修改其值的字符串,此時若是不拷貝字符串,那麼設置完屬性之後,字符串的值就可能會在對象不知情的情況下遭人更改。所以,這時就要拷貝一份“不可變”的字符串,確保對象中的字符串值不會無意間變動。只要實現屬性所用的對象是“可變的”,就應該在設置新屬性值時拷貝一份。

相關推薦

推薦中...