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