iOS面試攻略下篇:Objective-C面試題和基本概念
歡迎查看上篇:iOS面試攻略上篇:Objective-C關(guān)鍵字和概念
1、Object-C有多繼承嗎?沒有的話用什么代替?cocoa 中所有的類都是NSObject 的子類
多繼承在這里是用protocol 委托代理 來實現(xiàn)的
你不用去考慮繁瑣的多繼承 ,虛基類的概念.
ood的多態(tài)特性 在 obj-c 中通過委托來實現(xiàn).
2、Object-C有私有方法嗎?私有變量呢?
objective-c – 類里面的方法只有兩種, 靜態(tài)方法和實例方法. 這似乎就不是完整的面向?qū)ο罅?按照OO的原則就是一個對象只暴露有用的東西. 如果沒有了私有方法的話, 對于一些小范圍的代碼重用就不那么順手了. 在類里面聲名一個私有方法
@interface Controller : NSObject { NSString *something; }
+ (void)thisIsAStaticMethod;
– (void)thisIsAnInstanceMethod;
@end
@interface Controller (private) -
(void)thisIsAPrivateMethod;
@end
@private可以用來修飾私有變量
在Objective‐C中,所有實例變量默認都是私有的,所有實例方法默認都是公有的
3、關(guān)鍵字const什么含義?
const意味著”只讀”,下面的聲明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前兩個的作用是一樣,a是一個常整型數(shù)。第三個意味著a是一個指向常整型數(shù)的指針(也就是,整型數(shù)是不可修改的,但指針可以)。第四個意思a是一個指向整 型數(shù)的常指針(也就是說,指針指向的整型數(shù)是可以修改的,但指針是不可修改的)。***一個意味著a是一個指向常整型數(shù)的常指針(也就是說,指針指向的整型 數(shù)是不可修改的,同時指針也是不可修改的)。
結(jié)論:
•; 關(guān)鍵字const的作用是為給讀你代碼的人傳達非常有用的信息,實際上,聲明一個參數(shù)為常量是為了告訴了用戶這個參數(shù)的應(yīng)用目的。如果你曾花很多時間清理其它人留下的垃圾,你就會很快學(xué)會感謝這點多余的信息。(當然,懂得用const的程序員很少會留下的垃圾讓別人來清理的。)
•; 通過給優(yōu)化器一些附加的信息,使用關(guān)鍵字const也許能產(chǎn)生更緊湊的代碼。
•; 合理地使用關(guān)鍵字const可以使編譯器很自然地保護那些不希望被改變的參數(shù),防止其被無意的代碼修改。簡而言之,這樣可以減少bug的出現(xiàn)。
欲阻止一個變量被改變,可以使用 const 關(guān)鍵字。在定義該 const 變量時,通常需要對它進行初
始化,因為以后就沒有機會再去改變它了;
(2)對指針來說,可以指定指針本身為 const,也可以指定指針所指的數(shù)據(jù)為 const,或二者同時指定為 const;
(3)在一個函數(shù)聲明中,const 可以修飾形參,表明它是一個輸入?yún)?shù),在函數(shù)內(nèi)部不能改變其值;
(4)對于類的成員函數(shù),若指定其為 const 類型,則表明其是一個常函數(shù),不能修改類的成員變量;
(5)對于類的成員函數(shù),有時候必須指定其返回值為 const 類型,以使得其返回值不為“左值”。
4、關(guān)鍵字volatile有什么含義?并給出三個不同例子?
一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設(shè)這個變量的值了。精確地說就是,優(yōu)化器在用到
這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個例子:
并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)
一個中斷服務(wù)子程序中會訪問到的非自動變量(Non-automatic variables)
多線程應(yīng)用中被幾個任務(wù)共享的變量
一個參數(shù)既可以是const還可以是volatile嗎?解釋為什么。
一個指針可以是volatile 嗎?解釋為什么。
下面是答案:
是的。一個例子是只讀的狀態(tài)寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程序不應(yīng)該試圖去修改它。
是的。盡管這并不很常見。一個例子是當一個中服務(wù)子程序修該一個指向一個buffer的指針時。
static作用?
函數(shù)體內(nèi) static 變量的作用范圍為該函數(shù)體,不同于 auto 變量,該變量的內(nèi)存只被分配一次,
因此其值在下次調(diào)用時仍維持上次的值;
(2)在模塊內(nèi)的 static 全局變量可以被模塊內(nèi)所用函數(shù)訪問,但不能被模塊外其它函數(shù)訪問;
(3)在模塊內(nèi)的 static 函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用,這個函數(shù)的使用范圍被限制在聲明
它的模塊內(nèi);
(4)在類中的 static 成員變量屬于整個類所擁有,對類的所有對象只有一份拷貝;
(5)在類中的 static 成員函數(shù)屬于整個類所擁有,這個函數(shù)不接收 this 指針,因而只能訪問類的static 成員變量。
6、#import和#include的區(qū)別,@class代表什么?
@class一般用于頭文件中需要聲明該類的某個實例變量的時候用到,在m文件中還是需要使用#import
而#import比起#include的好處就是不會引起重復(fù)包含
7、線程和進程的區(qū)別?
進程和線程都是由操作系統(tǒng)所體會的程序運行的基本單元,系統(tǒng)利用該基本單元實現(xiàn)系統(tǒng)對應(yīng)用的并發(fā)性。
進程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式。進程有獨立的地址空間,一個進程崩潰后,在保護模式下不會對其它進程產(chǎn)生影響,而線程只是一 個進程中的不同執(zhí)行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進程死掉,所以多進程的程序要比多線程的程 序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對于一些要求同時進行并且又要共享某些變量的并發(fā)操作,只能用線程,不能用進程。
8、堆和棧的區(qū)別?
管理方式:對于棧來講,是由編譯器自動管理,無需我們手工控制;對于堆來說,釋放工作由程序員控制,容易產(chǎn)生memory leak。
申請大小:
棧:在Windows下,棧是向低地址擴展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存的區(qū)域。這句話的意思是棧頂?shù)牡刂泛蜅5?**容量是系統(tǒng)預(yù)先規(guī)定好的,在 WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數(shù)),如果申請的空間超過棧的剩余空間時,將提示overflow。因 此,能從棧獲得的空間較小。
堆:堆是向高地址擴展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域。這是由于系統(tǒng)是用鏈表來存儲的空閑內(nèi)存地址的,自然是不連續(xù)的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計算機系統(tǒng)中有效的虛擬內(nèi)存。由此可見,堆獲得的空間比較靈活,也比較大。
碎片問題:對于堆來講,頻繁的new/delete勢必會造成內(nèi)存空間的不連續(xù),從而造成大量的碎片,使程序效率降低。對于棧來講,則不會存在這個問題,因為棧是先進后出的隊列,他們是如此的一一對應(yīng),以至于永遠都不可能有一個內(nèi)存塊從棧中間彈出
分配方式:堆都是動態(tài)分配的,沒有靜態(tài)分配的堆。棧有2種分配方式:靜態(tài)分配和動態(tài)分配。靜態(tài)分配是編譯器完成的,比如局部變量的分配。動態(tài)分配由alloca函數(shù)進行分配,但是棧的動態(tài)分配和堆是不同的,他的動態(tài)分配是由編譯器進行釋放,無需我們手工實現(xiàn)。
分配效率:棧是機器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu),計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執(zhí)行,這就決定了棧的效率比較高。堆則是C/C++函數(shù)庫提供的,它的機制是很復(fù)雜的。
9、Object-C的內(nèi)存管理?
1.當你使用new,alloc和copy方法創(chuàng)建一個對象時,該對象的保留計數(shù)器值為1.當你不再使用該對象時,你要負責(zé)向該對象發(fā)送一條release或autorelease消息.這樣,該對象將在使用壽命結(jié)束時被銷毀.
2.當你通過任何其他方法獲得一個對象時,則假設(shè)該對象的保留計數(shù)器值為1,而且已經(jīng)被設(shè)置為自動釋放,你不需要執(zhí)行任何操作來確保該對象被清理.如果你打算在一段時間內(nèi)擁有該對象,則需要保留它并確保在操作完成時釋放它.
3.如果你保留了某個對象,你需要(最終)釋放或自動釋放該對象.必須保持retain方法和release方法的使用次數(shù)相等.
10、為什么很多內(nèi)置的類,如TableViewController的delegate的屬性是assign不是retain?
循環(huán)引用
所有的引用計數(shù)系統(tǒng),都存在循環(huán)應(yīng)用的問題。例如下面的引用關(guān)系:
對象a創(chuàng)建并引用到了對象b.
對象b創(chuàng)建并引用到了對象c.
對象c創(chuàng)建并引用到了對象b.
這時候b和c的引用計數(shù)分別是2和1。當a不再使用b,調(diào)用release釋放對b的所有權(quán),因為c還引用了b,所以b的引用計數(shù)為1,b不會被釋放。b不釋放,c的引用計數(shù)就是1,c也不會被釋放。從此,b和c永遠留在內(nèi)存中。
這種情況,必須打斷循環(huán)引用,通過其他規(guī)則來維護引用關(guān)系。比如,我們常見的delegate往往是assign方式的屬性而不是retain方式的屬 性,賦值不會增加引用計數(shù),就是為了防止delegation兩端產(chǎn)生不必要的循環(huán)引用。如果一個UITableViewController 對象a通 過retain獲取了UITableView對象b的所有權(quán),這個UITableView對象b的delegate又是a,如果這個delegate是 retain方式的,那基本上就沒有機會釋放這兩個對象了。自己在設(shè)計使用delegate模式時,也要注意這點。
11、定義屬性時,什么情況使用copy、assign、retain?
assign用于簡單數(shù)據(jù)類型,如NSInteger,double,bool,
retain和copy用于對象,
copy用于當a指向一個對象,b也想指向同樣的對象的時候,如果用assign,a如果釋放,再調(diào)用b會crash,如果用copy 的方式,a和b各自有自己的內(nèi)存,就可以解決這個問題。
retain 會使計數(shù)器加一,也可以解決assign的問題。
另外:atomic和nonatomic用來決定編譯器生成的getter和setter是否為原子操作。在多線程環(huán)境下,原子操作是必要的,否則有可能引起錯誤的結(jié)果。
加了atomic,setter函數(shù)會變成下面這樣:
if (property != newValue) {
[property release];
property = [newValue retain];
}
12、對象是什么時候被release的?
引用計數(shù)為0時。
autorelease實際上只是把對release的調(diào)用延遲了,對于每一個Autorelease,系統(tǒng)只是把該Object放入了當前的 Autorelease pool中,當該pool被釋放時,該pool中的所有Object會被調(diào)用Release。對于每一個Runloop,系統(tǒng)會 隱式創(chuàng)建一個Autorelease pool,這樣所有的release pool會構(gòu)成一個象CallStack一樣的一個棧式結(jié)構(gòu),在每一個 Runloop結(jié)束時,當前棧頂?shù)腁utorelease pool會被銷毀,這樣這個pool里的每個Object(就是autorelease的對 象)會被release。那什么是一個Runloop呢?一個UI事件,Timer call, delegate call, 都會是一個新的 Runloop
13、iOS有沒有垃圾回收?
Objective-C 2.0也是有垃圾回收機制的,但是只能在Mac OS X Leopard 10.5 以上的版本使用。
14、tableView的重用機制?
查看UITableView頭文件,會找到NSMutableArray* visiableCells,和 NSMutableDictnery* reusableTableCells兩個結(jié)構(gòu)。visiableCells內(nèi)保存當前顯示的 cells,reusableTableCells保存可重用的cells。
TableView顯示之初,reusableTableCells為空,那么 tableView dequeueReusableCellWithIdentifier:CellIdentifier返回nil。開始的cell都 是通過 [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 來創(chuàng)建,而且cellForRowAtIndexPath只是調(diào)用***顯示cell數(shù)的次數(shù)。
比如:有100條數(shù)據(jù),iPhone一屏最多顯示10個cell。程序最開始顯示TableView的情況是:
1.用 [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 創(chuàng)建10次cell,并給cell指定同樣的重用標識(當然,可以為不同顯示類型的cell指定不同的標識)。并且10個cell全部都加入到 visiableCells數(shù)組,reusableTableCells為空。
2.向下拖動tableView,當cell1完全移出屏幕,并且cell11(它也是alloc出來的,原因同上)完全顯示出來的時候。 cell11加入到visiableCells,cell1移出visiableCells,cell1加入到reusableTableCells。
3.接著向下拖動tableView,因為reusableTableCells中已經(jīng)有值,所以,當需要顯示新的 cell,cellForRowAtIndexPath再次被調(diào)用的時 候,tableView dequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。 cell1加入到visiableCells,cell1移出reusableTableCells;cell2移出 visiableCells,cell2加入到reusableTableCells。之后再需要顯示的Cell就可以正常重用了。
15、ViewController 的loadView、viewDidLoad、viewDidUnload分別是什么時候調(diào)用的,在自定義ViewCointroller時在這幾個函數(shù)中應(yīng)該做什么工作?
由init、loadView、viewDidLoad、viewDidUnload、dealloc的關(guān)系說起
init方法
在init方法中實例化必要的對象(遵從LazyLoad思想)
init方法中初始化ViewController本身
loadView方法
當view需要被展示而它卻是nil時,viewController會調(diào)用該方法。不要直接調(diào)用該方法。
如果手工維護views,必須重載重寫該方法
如果使用IB維護views,必須不能重載重寫該方法
loadView和IB構(gòu)建view
你在控制器中實現(xiàn)了loadView方法,那么你可能會在應(yīng)用運行的某個時候被內(nèi)存管理控制調(diào)用。 如果設(shè)備內(nèi)存不足的時候, view 控制器會收到 didReceiveMemoryWarning的消息。 默認的實現(xiàn)是檢查當前控制器的view是否在使用。如果它的view不在當前正在使用的 view hierarchy里面,且你的控制器實現(xiàn)了loadView方法,那么這個view將被release, loadView方法將被再次調(diào)用 來創(chuàng)建一個新的view。
viewDidLoad方法
viewDidLoad 此方法只有當view從nib文件初始化的時候才被調(diào)用。
重載重寫該方法以進一步定制view
在iPhone OS 3.0及之后的版本中,還應(yīng)該重載重寫viewDidUnload來釋放對view的任何索引
viewDidLoad后調(diào)用數(shù)據(jù)Model
viewDidUnload方法
當系統(tǒng)內(nèi)存吃緊的時候會調(diào)用該方法(注:viewController沒有被dealloc)
內(nèi)存吃緊時,在iPhone OS 3.0之前didReceiveMemoryWarning是釋放無用內(nèi)存的唯一方式,但是OS 3.0及以后viewDidUnload方法是更好的方式
在該方法中將所有IBOutlet(無論是property還是實例變量)置為nil(系統(tǒng)release view時已經(jīng)將其release掉了)
在該方法中釋放其他與view有關(guān)的對象、其他在運行時創(chuàng)建(但非系統(tǒng)必須)的對象、在viewDidLoad中被創(chuàng)建的對象、緩存數(shù)據(jù) 等 release對象后,將對象置為nil(IBOutlet只需要將其置為nil,系統(tǒng)release view時已經(jīng)將其release掉了)
一般認為viewDidUnload是viewDidLoad的鏡像,因為當view被重新請求時,viewDidLoad還會重新被執(zhí)行
viewDidUnload中被release的對象必須是很容易被重新創(chuàng)建的對象(比如在viewDidLoad或其他方法中創(chuàng)建的對象),不要release用戶數(shù)據(jù)或其他很難被重新創(chuàng)建的對象
dealloc方法
viewDidUnload和dealloc方法沒有關(guān)聯(lián),dealloc還是繼續(xù)做它該做的事情
16、ViewController的didReceiveMemoryWarning是在什么時候調(diào)用的?默認的操作是什么?
當程序接到內(nèi)存警告時View Controller將會收到這個消息:didReceiveMemoryWarning
從iOS3.0開始,不需要重載這個函數(shù),把釋放內(nèi)存的代碼放到viewDidUnload中去。
這個函數(shù)的默認實現(xiàn)是:檢查controller是否可以安全地釋放它的view(這里加粗的view指的是controller的view屬性),比如view本身沒有superview并且可以被很容易地重建(從nib或者loadView函數(shù))。
如果view可以被釋放,那么這個函數(shù)釋放view并調(diào)用viewDidUnload。
你可以重載這個函數(shù)來釋放controller中使用的其他內(nèi)存。但要記得調(diào)用這個函數(shù)的super實現(xiàn)來允許父類(一般是UIVIewController)釋放view。
如果你的ViewController保存著view的子view的引用,那么,在早期的iOS版本中,你應(yīng)該在這個函數(shù)中來釋放這些引用。而在iOS3.0或更高版本中,你應(yīng)該在viewDidUnload中釋放這些引用。
17、列舉Cocoa中常見的集中多線程的實現(xiàn),并談?wù)劧嗑€程安全的幾種解決辦法,一般什么地方會用到多線程?
NSThread,GCD等。盡量用上層分裝好的方法去實現(xiàn)多線程而不是手動調(diào)用NSThread。
18、怎么理解MVC,在Cocoa中MVC是怎么實現(xiàn)的?
Model: 代表你的應(yīng)用程序是什么(不是怎么展現(xiàn))
Controller: 控制你的Model怎么展現(xiàn)給用戶(UI邏輯)
View: Controller的奴隸。。。
1 Model,Controller,View相互通訊的規(guī)則:
Controller可以直接和Model通信
Controller也可以直接和View通信
Model和View永遠不能直接通信
iOS中View和Controller的通信是透明和固定的,主要通過outlet和action實現(xiàn)
View使用Delegate接口和Controller同步信息
View不直接和數(shù)據(jù)通信,使用dataSource接口從Controller處獲取數(shù)據(jù)
View的delegate和dataSource一般就是Controller
Controller負責(zé)為View翻譯和格式化Model的數(shù)據(jù)
Model使用Notification & KVO的方式分發(fā)數(shù)據(jù)更新信息,Controller可以有選擇的監(jiān)聽自己感興趣的信息。
View也可以監(jiān)聽廣播信息,但一般不是Model發(fā)出的信息
一個完整的App就是很多MVC的集合
19、delegate和notification區(qū)別,分別在什么情況下使用?
Delegate:
消息的發(fā)送者(sender)告知接收者(receiver)某個事件將要發(fā)生,delegate同意然然后發(fā)送者響應(yīng)事件,delegate機制使得接收者可以改變發(fā)送者的行為。通常發(fā)送者和接收者的關(guān)系是直接的一對多的關(guān)系。
Notification:
消息的發(fā)送者告知接收者事件已經(jīng)發(fā)生或者將要發(fā)送,僅此而已,接收者并不能反過來影響發(fā)送者的行為。通常發(fā)送者和接收者的關(guān)系是間接的多對多關(guān)系。
1. 效率肯定是delegate比nsnotification高。
2. delegate方法比notification更加直接,最典型的特征是,delegate方法往往需要關(guān)注返回值,也就是delegate方法 的結(jié)果。比如-windowShouldClose:,需要關(guān)心返回的是yes還是no。所以delegate方法往往包含should這個很傳神的詞。 也就是好比你做我的delegate,我會問你我想關(guān)閉窗口你愿意嗎?你需要給我一個答案,我根據(jù)你的答案來決定如何做下一步。相反 的,notification***的特色就是不關(guān)心接受者的態(tài)度,我只管把通告放出來,你接受不接受就是你的事情,同時我也不關(guān)心結(jié)果。所以 notification往往用did這個詞匯,比如NSWindowDidResizeNotification,那么nswindow對象放出這個 notification后就什么都不管了也不會等待接受者的反應(yīng)。
1)兩個模塊之間聯(lián)系不是很緊密,就用notification傳值,例如多線程之間傳值用notificaiton。
2)delegate只是一種較為簡單的回調(diào),且主要用在一個模塊中,例如底層功能完成了,需要把一些值傳到上層去,就事先把上層的函數(shù)通過 delegate傳到底層,然后在底層call這個delegate,它們都在一個模塊中,完成一個功能,例如 說 NavgationController 從 B 界面到A 點返回按鈕 (調(diào)用popViewController方法) 可以用delegate 比較好。
別走開,下頁更精彩
#p#
20、self.跟self什么區(qū)別?
21、id、nil代表什么?
id和void *并非完全一樣。在上面的代碼中,id是指向struct objc_object的一個指針,這個意思基本上是說,id是一個指向任何 一個繼承了Object(或者NSObject)類的對象。需要注意的是id是一個指針,所以你在使用id的時候不需要加星號。比如id foo=nil 定義了一個nil指針,這個指針指向NSObject的一個任意子類。而id *foo=nil則定義了一個指針,這個指針指向另一個指針,被指向的這個 指針指向NSObject的一個子類。
nil和C語言的NULL相同,在objc/objc.h中定義。nil表示一個Objctive-C對象,這個對象的指針指向空(沒有東西就是空)。
首字母大寫的Nil和nil有一點不一樣,Nil定義一個指向空的類(是Class,而不是對象)。
SEL是“selector”的一個類型,表示一個方法的名字
Method(我們常說的方法)表示一種類型,這種類型與selector和實現(xiàn)(implementation)相關(guān)
IMP定義為 id (*IMP) (id, SEL, …)。這樣說來, IMP是一個指向函數(shù)的指針,這個被指向的函數(shù)包括id(“self”指針),調(diào)用的SEL(方法名),再加上一些其他參數(shù).說白了IMP就是實現(xiàn)方法。
22、內(nèi)存管理 Autorelease、retain、copy、assign的set方法和含義?
1,你初始化(alloc/init)的對象,你需要釋放(release)它。例如:
NSMutableArray aArray = [[NSArray alloc] init]; 后,需要 [aArray release];
2,你retain或copy的,你需要釋放它。例如:
[aArray retain] 后,需要 [aArray release];
3,被傳遞(assign)的對象,你需要斟酌的retain和release。例如:
obj2 = [[obj1 someMethod] autorelease];
對象2接收對象1的一個自動釋放的值,或傳遞一個基本數(shù)據(jù)類型(NSInteger,NSString)時:你或希望將對象2進行retain,以防止它在被使用之前就被自動釋放掉。但是在retain后,一定要在適當?shù)臅r候進行釋放。
關(guān)于索引計數(shù)(Reference Counting)的問題
retain值 = 索引計數(shù)(Reference Counting)
NSArray對象會retain(retain值加一)任何數(shù)組中的對象。當NSArray被卸載(dealloc)的時候,所有數(shù)組中的對象會被 執(zhí)行一次釋放(retain值減一)。不僅僅是NSArray,任何收集類(Collection Classes)都執(zhí)行類似操作。例如 NSDictionary,甚至UINavigationController。
Alloc/init建立的對象,索引計數(shù)為1。無需將其再次retain。
[NSArray array]和[NSDate date]等“方法”建立一個索引計數(shù)為1的對象,但是也是一個自動釋放對象。所以是本地臨時對象,那么無所謂了。如果是打算在全Class中使用的變量(iVar),則必須retain它。
缺省的類方法返回值都被執(zhí)行了“自動釋放”方法。(*如上中的NSArray)
在類中的卸載方法“dealloc”中,release所有未被平衡的NS對象。(*所有未被autorelease,而retain值為1的)
23、類別的作用?
有時我們需要在一個已經(jīng)定義好的類中增加一些方法,而不想去重寫該類。比如,當工程已經(jīng)很大,代碼量比較多,或者類中已經(jīng)包住很多方法,已經(jīng)有其他代碼調(diào)用了該類創(chuàng)建對象并使用該類的方法時,可以使用類別對該類擴充新的方法。
注意:類別只能擴充方法,而不能擴充成員變量。
24、委托(舉例)
委托代理(degegate),顧名思義,把某個對象要做的事情委托給別的對象去做。那么別的對象就是這個對象的代理,代替它來打理要做的事。反映到程序中,首先要明確一個對象的委托方是哪個對象,委托所做的內(nèi)容是什么。
委托機制是一種設(shè)計模式,在很多語言中都用到的,這只是個通用的思想,網(wǎng)上會有很多關(guān)于這方面的介紹。
那么在蘋果開發(fā)過程中,用到委托的程序?qū)崿F(xiàn)思想如下,我主要拿如何在視圖之間傳輸信息做個例子。
譬如:在兩個頁面(UIIview視圖對象)實現(xiàn)傳值,用委托(delegate)可以很好做到!
方法:
類A
@interface A:UIView
id transparendValueDelegate;
@property(nomatic, retain) id transparendValueDelegate;
@end
@implemtion A
@synthesize transparendValueDelegate
-(void)Function
{
NSString* value = @"hello";
//讓代理對象執(zhí)行transparendValue動作
[transparendValueDelegate transparendValue: value];
}
@end
類B
@interface B:UIView
NSString* value;
@end
@implemtion B
-(void)transparendValue:(NSString*)fromValue
{
value = fromValue;
NSLog(@"the value is %@ ",value);
}
@end
//下面的設(shè)置A代理委托對象為B
//在定義A和B類對象處:
A* a = [[A alloc] init];
B* b = [[B alloc] init];
a. transparendValueDelegate = b;//設(shè)置對象a代理為對象b
這樣在視圖A和B之間可以通過委托來傳值!
25、retainCount?
26..屬性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那種情況下用
assign:指定setter方法用簡單的賦值,這是默認操作。你可以對標量類型(如int)使用這個屬性。你可以想象一個float,它不是一個對象,所以它不能retain、copy。
retain:指定retain應(yīng)該在后面的對象上調(diào)用,前一個值發(fā)送一條release消息。你可以想象一個NSString實例,它是一個對象,而且你可能想要retain它。
copy:指定應(yīng)該使用對象的副本(深度復(fù)制),前一個值發(fā)送一條release消息?;旧舷駌etain,但是沒有增加引用計數(shù),是分配一塊新的內(nèi)存來放置它。
readonly:將只生成getter方法而不生成setter方法(getter方法沒有g(shù)et前綴)。
readwrite:默認屬性,將生成不帶額外參數(shù)的getter和setter方法(setter方法只有一個參數(shù))。
atomic:對于對象的默認屬性,就是setter/getter生成的方法是一個原子操作。如果有多個線程同時調(diào)用setter的話,不會出現(xiàn)某一個線程執(zhí)行setter全部語句之前,另一個線程開始執(zhí)行setter的情況,相關(guān)于方法頭尾加了鎖一樣。
nonatomic:不保證setter/getter的原子性,多線程情況下數(shù)據(jù)可能會有問題。
27.類變量的@protected ,@private ,@public ,@package聲明各有什么含義
Objective-C 對存取權(quán)限的設(shè)定。也是變量的作用域。
protected 該類和所有的子類中的方法可以直接訪問這樣的變量,這是默認的。
private — 該類中的方法可以訪問這樣的變量,子類不可以。 public — 除了自己和子類中的方法外,也可以被其他類或者其他模塊中的方法所訪問。開放性***。 package — 對于64位圖像,這樣的成員變量可以在實現(xiàn)這個類的圖像中隨意訪問。
28.淺拷貝和深拷貝區(qū)別是什么
簡單的來說就是,在有指針的情況下,淺拷貝只是增加了一個指針指向已經(jīng)存在的內(nèi)存,而深拷貝就是增加一個指針并且申請一個新的內(nèi)存,使這個增加的指針指向這個新的內(nèi)存,采用深拷貝的情況下,釋放內(nèi)存的時候就不會出現(xiàn)在淺拷貝時重復(fù)釋放同一內(nèi)存的錯誤
29.Cocoa中與虛基類的概念么?怎么簡潔的實現(xiàn)
30.NSString 和 NSMutableString 有什么區(qū)別
NSString相當于一個const char* 不可以改變。
而 NSMutableString相當于 char* 可以改變內(nèi)部的內(nèi)容。
31.自動釋放池跟GC有什么區(qū)別?iPhone上有GC么?[pool release] 和[pool drain]有什么區(qū)別
”Autorelease Pools”(自動釋放池)在應(yīng)用中的使用技巧。
1,Autorelease Pools概要
一個”Autorelease Pool”實例中“包含”其它各種調(diào)用了”autorelease”方法的對象。當它釋放時,其中所有被管理對象都會收 到”relrease”的消信。注意,同一個對象可以被多次調(diào)用”autorelease”方法,并可以放到同一個”Autorelease Pool” 中。引入這個自動釋放池機制,對象的”autorelease”方法代替”relrease”方法可以延長它的生命周期,直接到當 前”Autorelrease Pool”釋放。如果想讓此對象的生命周期超過”Autorelease Pool”,還可以再次”retain”,呵 呵,有意思吧?且讓我慢慢道來。
Cocoa總是認為當前至少有一個”Autorelease Pool”對象是可用的。若此對象并不存在,你調(diào)用的”autorelease”的所有對象都不會被自動釋放掉,可想而知,造成內(nèi)存泄露。Cocoa把這個錯誤信息寫入日志??僅僅是為了以后分析。
你可以用”alloc”與”init”方法創(chuàng)建一個”NSAutoreleasePool”對象,并且可以調(diào)用”release”或”drain” (”release”與”drain”的區(qū)別是”drain”在有GC的環(huán)境中會引起GC回收操作,”release”反之。但在非GC環(huán)境中,兩者相 同。官方的說法是為了程序的兼容性,應(yīng)該考慮用”drain”代替”release”,)方法來回收它(調(diào)用它的”autorelease” 或”retain”方法會引起異常)。在一個完整的上下文***”Autorelease Pool”對象應(yīng)該被”release”掉(在方法內(nèi)或一段循環(huán) 體內(nèi)創(chuàng)建的”Autorelease Pool”對象)。
“Autorelease Pools”的所有實例在棧中管理(我們暫時叫他“自動釋放池棧”),并且它們是可以被嵌套的(父生子,子生孫。。。子子孫 孫 ^_^)。例如,當我們創(chuàng)建一個”Autorelease Pool”對象后,它就被自動放到“自動釋放池棧”的棧頂。當本池對象回收時,它就隨之從 這個棧中POP掉。那么也就是說,當任何一個對象調(diào)用”autorelease”方法后,它會被放入當前線程中當前棧頂?shù)淖詣俞尫懦刂小?/p>
接下來我們聊聊”Autorelease Pools”的嵌套問題。在你的應(yīng)用中,你可以任意多的創(chuàng)建”Autorelease Pool”對象,而這些 對象被當前線程的“自動釋放池棧”所管理。那么除了一個接一個的順序創(chuàng)建并銷毀它的情況外,還有一種使用方式,就是嵌套式的創(chuàng)建與使用。例如:在你的主函 數(shù)創(chuàng)建了一個”autorelease pool”,然后又調(diào)用了創(chuàng)建了”autorelease pool”實例的其它方法;或是在外循環(huán)中創(chuàng)建 了”Autorelease Pool”的實例,而內(nèi)循環(huán)中也做了相同的事情。有意思吧,呵呵,嵌套的機制使父Pool實例釋放后,它的所有子Pool也 將釋放。但這里還存在一些副作用,后續(xù)文章會詳細討論。
“Application kit”在一個事件循環(huán)里會自動創(chuàng)建一個”autorelease pool”。像鼠標鍵的按下與釋放,所以你編寫的代碼通常不需要考慮太多這方面的事情。當然,有以下三種情況你會創(chuàng)建與銷毀自己的Pool實例:
1,應(yīng)用不是基于”Application Kit”,像”Command-line tool”,因為它并沒有內(nèi)置的”autorelease pools”的支持。
2,創(chuàng)建線程,你必需在線程開始時創(chuàng)建一個”Autorelease Pool”實例。反之,會造成內(nèi)存池露(會在以后的文章詳細說明線程與池的技巧)。
3,一個循環(huán)內(nèi)創(chuàng)建了太多的臨時對象,你應(yīng)該為他們創(chuàng)建一個”Autorelease Pool”對象,并在下次循還前銷毀它們。
2,自動釋放池中的”Non-AppKit”應(yīng)用
在”Non-AppKit”應(yīng)用中使用自動釋放池的機制其實是相當簡單的事情。你僅僅需要在main()起始處創(chuàng)建”Autorelease Pool” 對象,并在結(jié)尾處釋放掉它。就像在Xcode的Foundation Tool的創(chuàng)建模版里寫的一樣。這個確保你在應(yīng)用生命周期內(nèi)至少有一 個”Autorelease Pool”是可用的。但是,這也使所有在此期間的所有”autorelease”的對象都必需在應(yīng)用結(jié)束后才被釋放。這也許 會引起在應(yīng)用的使用中不斷的增長,所以,你仍然考慮在不同的作用域創(chuàng)建新的”Autorelease Pool”。
大多應(yīng)用中都存在各種級別的循環(huán)機制。在這些應(yīng)用中,你可以在每個循環(huán)內(nèi)的開頭創(chuàng)建一個”Autorelease Pool”對象,并在結(jié)尾處釋放掉它。
例如:
void main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *args = [[NSProcessInfo processInfo] arguments];
unsigned count, limit = [args count];
for (count = 0; count < limit; count++)
{
NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
NSString *fileContents;
NSString *fileName;
fileName = [args objectAtIndex:count];
fileContents = [[[NSString alloc] initWithContentsOfFile:fileName] autorelease];
// this is equivalent to using stringWithContentsOfFile:
[loopPool release];
}
[pool drain];
exit (EXIT_SUCCESS);
}
在命令行中處理所有以參數(shù)傳來的文件。一次循環(huán)處理一個文件。在循環(huán)的開頭創(chuàng)建一個”NSAutoreleasePool”對象,并在循環(huán)結(jié)束時釋放掉。 因此,任何在其中創(chuàng)建并調(diào)用“autorelease”的對象都將添加到這個Pool實例中,當本池被釋放后,這些對象也將被回收。注意,任何在作用域內(nèi) 創(chuàng)建的”autoreleased”對象(像”fileName”),雖然并沒有顯示的調(diào)用”autorelease”方法,但都將被當前池所管理并釋 放。
32.C和obj-c 如何混用
1)obj-c的編譯器處理后綴為m的文件時,可以識別obj-c和c的代碼,處理mm文件可以識別obj-c,c,c++代碼,但cpp文件必須只能用c/c++代碼,而且cpp文件include的頭文件中,也不能出現(xiàn)obj-c的代碼,因為cpp只是cpp
2)在mm文件中混用cpp直接使用即可,所以obj-c混cpp不是問題
3)在cpp中混用obj-c其實就是使用obj-c編寫的模塊是我們想要的。
如果模塊以類實現(xiàn),那么要按照cpp class的標準寫類的定義,頭文件中不能出現(xiàn)obj-c的東西,包括#import cocoa的。實現(xiàn)文件中,即類的實現(xiàn)代碼中可以使用obj-c的東西,可以import,只是后綴是mm。
如果模塊以函數(shù)實現(xiàn),那么頭文件要按c的格式聲明函數(shù),實現(xiàn)文件中,c++函數(shù)內(nèi)部可以用obj-c,但后綴還是mm或m。
總結(jié):只要cpp文件和cpp include的文件中不包含obj-c的東西就可以用了,cpp混用obj-c的關(guān)鍵是使用接口,而不能直接使用實現(xiàn)代 碼,實際上cpp混用的是obj-c編譯后的o文件,這個東西其實是無差別的,所以可以用。obj-c的編譯器支持cpp
33.響應(yīng)者鏈是什么
響應(yīng)者鏈是Application Kit事件處理架構(gòu)的中心機制。它由一系列鏈接在一起的響應(yīng)者對象組成,事件或者動作消息可以沿著這些對象進行傳 遞。如圖6-20顯示的那樣,如果一個響應(yīng)者對象不能處理某個事件或動作-也就是說,它不響應(yīng)那個消息,或者不認識那個事件,則將該消息重新發(fā)送給鏈中的 下一個響應(yīng)者。消息沿著響應(yīng)者鏈向上、向更高級別的對象傳遞,直到最終被處理(如果最終還是沒有被處理,就會被拋棄)。
當Application Kit在應(yīng)用程序中構(gòu)造對象時,會為每個窗口建立響應(yīng)者鏈。響應(yīng)者鏈中的基本對象是NSWindow對象及其視圖層次。在視圖層次中級別較低的視圖將比級別更高的視圖優(yōu)先獲得處理事件或動作消息的機會。NSWindow中保有一個***響應(yīng)者的引用,它通常是當前窗口中處于選擇狀態(tài)的視圖,窗口通常把響應(yīng)消息的機會首先給它。對于事件消息,響應(yīng)者鏈通常以發(fā)生事件的窗口對應(yīng)的NSWindow對象作為結(jié)束,雖然其它對象也可以作為下一個響應(yīng)者被加入到NSWindow對象的后面。
34..UIscrollVew用到了什么設(shè)計模式?還能再foundation庫中找到類似的嗎?
組合模式composition,所有的container view都用了這個模式
觀察者模式observer,所有的UIResponder都用了這個模式。
模板(Template)模式,所有datasource和delegate接口都是模板模式的典型應(yīng)用
33. .timer的間隔周期準嗎?為什么?怎樣實現(xiàn)一個精準的timer?
NSTimer可以精確到50-100毫秒.
NSTimer不是絕對準確的,而且中間耗時或阻塞錯過下一個點,那么下一個點就pass過去了
此份面試題包含40個題目,是現(xiàn)在網(wǎng)上能搜索到的一個比較熱的一份,但是答案并不是很詳細和完整,基本答案來著cocoaChina,和一些自己的補充。
34.Difference between shallow copy and deep copy?
淺復(fù)制和深復(fù)制的區(qū)別?
答案:淺層復(fù)制:只復(fù)制指向?qū)ο蟮闹羔槪粡?fù)制引用對象本身。
深層復(fù)制:復(fù)制引用對象本身。
意思就是說我有個A對象,復(fù)制一份后得到A_copy對象后,對于淺復(fù)制來說,A和A_copy指向的是同一個內(nèi)存資源,復(fù)制的只不過是是一個指針,對象本身資源
還是只有一份,那如果我們對A_copy執(zhí)行了修改操作,那么發(fā)現(xiàn)A引用的對象同樣被修改,這其實違背了我們復(fù)制拷貝的一個思想。深復(fù)制就好理解了,內(nèi)存中存在了
兩份獨立對象本身。
用網(wǎng)上一哥們通俗的話將就是:
淺復(fù)制好比你和你的影子,你完蛋,你的影子也完蛋
深復(fù)制好比你和你的克隆人,你完蛋,你的克隆人還活著。
別走開,下頁更精彩
#p#
35.What is advantage of categories? What is difference between implementing a category and inheritance?
類別的作用?繼承和類別在實現(xiàn)中有何區(qū)別?
答案:category 可以在不獲悉,不改變原來代碼的情況下往里面添加新的方法,只能添加,不能刪除修改。
并且如果類別和原來類中的方法產(chǎn)生名稱沖突,則類別將覆蓋原來的方法,因為類別具有更高的優(yōu)先級。
類別主要有3個作用:
(1)將類的實現(xiàn)分散到多個不同文件或多個不同框架中。
(2)創(chuàng)建對私有方法的前向引用。
(3)向?qū)ο筇砑臃钦絽f(xié)議。
繼承可以增加,修改或者刪除方法,并且可以增加屬性。
36.Difference between categories and extensions?
類別和類擴展的區(qū)別。
答案:category和extensions的不同在于后者可以添加屬性。另外后者添加的方法是必須要實現(xiàn)的。
extensions可以認為是一個私有的Category。
37.Difference between protocol in objective c and interfaces in java?
oc中的協(xié)議和java中的接口概念有何不同?
答案:OC中的代理有2層含義,官方定義為 formal和informal protocol。前者和Java接口一樣。
informal protocol中的方法屬于設(shè)計模式考慮范疇,不是必須實現(xiàn)的,但是如果有實現(xiàn),就會改變類的屬性。
其實關(guān)于正式協(xié)議,類別和非正式協(xié)議我很早前學(xué)習(xí)的時候大致看過,也寫在了學(xué)習(xí)教程里
“非正式協(xié)議概念其實就是類別的另一種表達方式“這里有一些你可能希望實現(xiàn)的方法,你可以使用他們更好的完成工作”。
這個意思是,這些是可選的。比如我門要一個更好的方法,我們就會申明一個這樣的類別去實現(xiàn)。然后你在后期可以直接使用這些更好的方法。
這么看,總覺得類別這玩意兒有點像協(xié)議的可選協(xié)議。"
現(xiàn)在來看,其實protocal已經(jīng)開始對兩者都統(tǒng)一和規(guī)范起來操作,因為資料中說“非正式協(xié)議使用interface修飾“,
現(xiàn)在我們看到協(xié)議中兩個修飾詞:“必須實現(xiàn)(@requied)”和“可選實現(xiàn)(@optional)”。
38.What are KVO and KVC?
答案:kvc:鍵 - 值編碼是一種間接訪問對象的屬性使用字符串來標識屬性,而不是通過調(diào)用存取方法,直接或通過實例變量訪問的機制。
很多情況下可以簡化程序代碼。apple文檔其實給了一個很好的例子。
kvo:鍵值觀察機制,他提供了觀察某一屬性變化的方法,極大的簡化了代碼。
具體用看到嗯哼用到過的一個地方是對于按鈕點擊變化狀態(tài)的的監(jiān)控。
比如我自定義的一個button
[cpp]
[self addObserver:self forKeyPath:@"highlighted" options:0 context:nil];
#pragma mark KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
([keyPath isEqualToString:@"highlighted"] ) {
[self setNeedsDisplay];
}
}
對于系統(tǒng)是根據(jù)keypath去取的到相應(yīng)的值發(fā)生改變,理論上來說是和kvc機制的道理是一樣的。
對于kvc機制如何通過key尋找到value:
“當通過KVC調(diào)用對象時,比如:[self valueForKey:@”someKey”]時,程序會自動試圖通過幾種不同的方式解析這個調(diào)用。首先 查找對象是否帶有 someKey 這個方法,如果沒找到,會繼續(xù)查找對象是否帶有someKey這個實例變量(iVar),如果還沒有找到,程序會繼續(xù) 試圖調(diào)用 -(id) valueForUndefinedKey:這個方法。如果這個方法還是沒有被實現(xiàn)的話,程序會拋出一個 NSUndefinedKeyException異常錯誤。
(cocoachina.com注:Key-Value Coding查找方法的時候,不僅僅會查找someKey這個方法,還會查找 getsomeKey這個方法,前面加一個get,或者_someKey以及_getsomeKey這幾種形式。同時,查找實例變量的時候也會不僅僅查找 someKey這個變量,也會查找_someKey這個變量是否存在。)
設(shè)計valueForUndefinedKey:方法的主要目的是當你使用-(id)valueForKey方法從對象中請求值時,對象能夠在錯誤發(fā)生前,有***的機會響應(yīng)這個請求。這樣做有很多好處,下面的兩個例子說明了這樣做的好處。“
來至cocoa,這個說法應(yīng)該挺有道理。
因為我們知道button卻是存在一個highlighted實例變量.因此為何上面我們只是add一個相關(guān)的keypath就行了,
可以按照kvc查找的邏輯理解,就說的過去了。
39.What is purpose of delegates?
代理的作用?
答案:代理的目的是改變或傳遞控制鏈。允許一個類在某些特定時刻通知到其他類,而不需要獲取到那些類的指針??梢詼p少框架復(fù)雜度。
另外一點,代理可以理解為java中的回調(diào)監(jiān)聽機制的一種類似。
40.What are mutable and immutable types in Objective C?
oc中可修改和不可以修改類型。
答案:可修改不可修改的集合類。這個我個人簡單理解就是可動態(tài)添加修改和不可動態(tài)添加修改一樣。
比如NSArray和NSMutableArray。前者在初始化后的內(nèi)存控件就是固定不可變的,后者可以添加等,可以動態(tài)申請新的內(nèi)存空間。
41.When we call objective c is runtime language what does it mean?
我們說的oc是動態(tài)運行時語言是什么意思?
答案:多態(tài)。 主要是將數(shù)據(jù)類型的確定由編譯時,推遲到了運行時。
這個問題其實淺涉及到兩個概念,運行時和多態(tài)。
簡單來說,運行時機制使我們直到運行時才去決定一個對象的類別,以及調(diào)用該類別對象指定方法。
多態(tài):不同對象以自己的方式響應(yīng)相同的消息的能力叫做多態(tài)。意思就是假設(shè)生物類(life)都用有一個相同的方法-eat;
那人類屬于生物,豬也屬于生物,都繼承了life后,實現(xiàn)各自的eat,但是調(diào)用是我們只需調(diào)用各自的eat方法。
也就是不同的對象以自己的方式響應(yīng)了相同的消息(響應(yīng)了eat這個選擇器)。
因此也可以說,運行時機制是多態(tài)的基礎(chǔ)?~~~
42.what is difference between NSNotification and protocol?
通知和協(xié)議的不同之處?
答案:協(xié)議有控制鏈(has-a)的關(guān)系,通知沒有。
首先我一開始也不太明白,什么叫控制鏈(專業(yè)術(shù)語了~)。但是簡單分析下通知和代理的行為模式,我們大致可以有自己的理解
簡單來說,通知的話,它可以一對多,一條消息可以發(fā)送給多個消息接受者。
代理按我們的理解,到不是直接說不能一對多,比如我們知道的明星經(jīng)濟代理人,很多時候一個經(jīng)濟人負責(zé)好幾個明星的事務(wù)。
只是對于不同明星間,代理的事物對象都是不一樣的,一一對應(yīng),不可能說明天要處理A明星要一個發(fā)布會,代理人發(fā)出處理發(fā)布會的消息后,別稱B的
發(fā)布會了。但是通知就不一樣,他只關(guān)心發(fā)出通知,而不關(guān)心多少接收到感興趣要處理。
因此控制鏈(has-a從英語單詞大致可以看出,單一擁有和可控制的對應(yīng)關(guān)系。
43.What is push notification?
什么是推送消息?
答案:太簡單,不作答~~~~~~~~~~
這是cocoa上的答案。
其實到不是說太簡單,只是太泛泛的一個概念的東西。就好比說,什么是人。
推送通知更是一種技術(shù)。
簡單點就是客戶端獲取資源的一種手段。
普通情況下,都是客戶端主動的pull。
推送則是服務(wù)器端主動push。
44.Polymorphism?
關(guān)于多態(tài)性
答案:多態(tài),子類指針可以賦值給父類。
這個題目其實可以出到一切面向?qū)ο笳Z言中,
因此關(guān)于多態(tài),繼承和封裝基本***都有個自我意識的理解,也并非一定要把書上資料上寫的能背出來。
最重要的是轉(zhuǎn)化成自我理解。
45.Singleton?
對于單例的理解
答案:11,12題目其實出的有點泛泛的感覺了,可能說是編程語言需要或是必備的基礎(chǔ)。
基本能用熟悉的語言寫出一個單例,以及可以運用到的場景或是你編程中碰到過運用的此種模式的框架類等。
進一步點,考慮下如何在多線程訪問單例時的安全性。
46.What is responder chain?
說說響應(yīng)鏈
答案: 事件響應(yīng)鏈。包括點擊事件,畫面刷新事件等。在視圖棧內(nèi)從上至下,或者從下之上傳播。
可以說點事件的分發(fā),傳遞以及處理。具體可以去看下touch事件這塊。因為問的太抽象化了
嚴重懷疑題目出到越后面就越籠統(tǒng)。
47.Difference between frame and bounds?
frame和bounds有什么不同?
答案:frame指的是:該view在父view坐標系統(tǒng)中的位置和大小。(參照點是父親的坐標系統(tǒng))
bounds指的是:該view在本身坐標系統(tǒng)中 的位置和大小。(參照點是本身坐標系統(tǒng))
48.Difference between method and selector?
方法和選擇器有何不同?
答案:selector是一個方法的名字,method是一個組合體,包含了名字和實現(xiàn).
詳情可以看apple文檔。
49.Is there any garbage collection mechanism in Objective C.?
OC的垃圾回收機制?
答案: OC2.0有Garbage collection,但是iOS平臺不提供。
一般我們了解的objective-c對于內(nèi)存管理都是手動操作的,但是也有自動釋放池。
但是差了大部分資料,貌似不要和arc機制搞混就好了。
求更多~~
50.NSOperation queue?
答案:存放NSOperation的集合類。
操作和操作隊列,基本可以看成java中的線程和線程池的概念。用于處理ios多線程開發(fā)的問題。
網(wǎng)上部分資料提到一點是,雖然是queue,但是卻并不是帶有隊列的概念,放入的操作并非是按照嚴格的先進現(xiàn)出。
這邊又有個疑點是,對于隊列來說,先進先出的概念是Afunc添加進隊列,Bfunc緊跟著也進入隊列,Afunc先執(zhí)行這個是必然的,
但是Bfunc是等Afunc完全操作完以后,B才開始啟動并且執(zhí)行,因此隊列的概念離亂上有點違背了多線程處理這個概念。
但是轉(zhuǎn)念一想其實可以參考銀行的取票和叫號系統(tǒng)。
因此對于A比B先排隊取票但是B率先執(zhí)行完操作,我們亦然可以感性認為這還是一個隊列。
但是后來看到一票關(guān)于這操作隊列話題的文章,其中有一句提到
“因為兩個操作提交的時間間隔很近,線程池中的線程,誰先啟動是不定的。”
瞬間覺得這個queue名字有點忽悠人了,還不如pool~
綜合一點,我們知道他可以比較大的用處在于可以幫組多線程編程就好了。
51.What is lazy loading?
答案:懶漢模式,只在用到的時候才去初始化。
也可以理解成延時加載。
我覺得***也最簡單的一個列子就是tableView中圖片的加載顯示了。
一個延時載,避免內(nèi)存過高,一個異步加載,避免線程堵塞。
52.Can we use two tableview controllers on one viewcontroller?
是否在一個視圖控制器中嵌入兩個tableview控制器?
答案:一個視圖控制只提供了一個View視圖,理論上一個tableViewController也不能放吧,
只能說可以嵌入一個tableview視圖。當然,題目本身也有歧義,如果不是我們定性思維認為的UIViewController,
而是宏觀的表示視圖控制者,那我們倒是可以把其看成一個視圖控制者,它可以控制多個視圖控制器,比如TabbarController
那樣的感覺。
53.Can we use one tableview with two different datasources? How you will achieve this?
一個tableView是否可以關(guān)聯(lián)兩個不同的數(shù)據(jù)源?你會怎么處理?
答案:首先我們從代碼來看,數(shù)據(jù)源如何關(guān)聯(lián)上的,其實是在數(shù)據(jù)源關(guān)聯(lián)的代理方法里實現(xiàn)的。
因此我們并不關(guān)心如何去關(guān)聯(lián)他,他怎么關(guān)聯(lián)上,方法只是讓我返回根據(jù)自己的需要去設(shè)置如相關(guān)的數(shù)據(jù)源。
因此,我覺得可以設(shè)置多個數(shù)據(jù)源啊,但是有個問題是,你這是想干嘛呢?想讓列表如何顯示,不同的數(shù)據(jù)源分區(qū)塊顯示?