1. ARC和MRC
Objective-c中提供了兩種內(nèi)存管理機(jī)制MRC(MannulReference Counting)和ARC(Automatic Reference Counting),分別提供對(duì)內(nèi)存的手動(dòng)和自動(dòng)管理,來(lái)滿足不同的需求。Xcode 4.1及其以前版本沒有ARC。
在MRC的內(nèi)存管理模式下,與對(duì)變量的管理相關(guān)的方法有:retain,release和autorelease。retain和release方法操作的是引用記數(shù),當(dāng)引用記數(shù)為零時(shí),便自動(dòng)釋放內(nèi)存。并且可以用NSAutoreleasePool對(duì)象,對(duì)加入自動(dòng)釋放池(autorelease調(diào)用)的變量進(jìn)行管理,當(dāng)drain時(shí)回收內(nèi)存。
retain,該方法的作用是將內(nèi)存數(shù)據(jù)的所有權(quán)附給另一指針變量,引用數(shù)加1,即retainCount+= 1;
release,該方法是釋放指針變量對(duì)內(nèi)存數(shù)據(jù)的所有權(quán),引用數(shù)減1,即retainCount-= 1;
autorelease,該方法是將該對(duì)象內(nèi)存的管理放到autoreleasepool中。
在ARC中與內(nèi)存管理有關(guān)的標(biāo)識(shí)符,可以分為變量標(biāo)識(shí)符和屬性標(biāo)識(shí)符,對(duì)于變量默認(rèn)為__strong,而對(duì)于屬性默認(rèn)為unsafe_unretained。也存在autoreleasepool。
其中assign/retain/copy與MRC下property的標(biāo)識(shí)符意義相同,strong類似與retain,assign類似于unsafe_unretained,strong/weak/unsafe_unretained與ARC下變量標(biāo)識(shí)符意義相同,只是一個(gè)用于屬性的標(biāo)識(shí),一個(gè)用于變量的標(biāo)識(shí)(帶兩個(gè)下劃短線__)。所列出的其他的標(biāo)識(shí)符與MRC下意義相同。
2. 線程和進(jìn)程
進(jìn)程,是并發(fā)執(zhí)行的程序在執(zhí)行過(guò)程中分配和管理資源的基本單位,是一個(gè)動(dòng)態(tài)概念,竟?fàn)幱?jì)算機(jī)系統(tǒng)資源的基本單位。每一個(gè)進(jìn)程都有一個(gè)自己的地址空間,即進(jìn)程空間或(虛空間)。進(jìn)程空間的大小 只與處理機(jī)的位數(shù)有關(guān),一個(gè) 16 位長(zhǎng)處理機(jī)的進(jìn)程空間大小為 216 ,而 32 位處理機(jī)的進(jìn)程空間大小為 232 。進(jìn)程至少有 5 種基本狀態(tài),它們是:初始態(tài),執(zhí)行態(tài),等待狀態(tài),就緒狀態(tài),終止?fàn)顟B(tài)。
線程,在網(wǎng)絡(luò)或多用戶環(huán)境下,一個(gè)服務(wù)器通常需要接收大量且不確定數(shù)量用戶的并發(fā)請(qǐng)求,為每一個(gè)請(qǐng)求都創(chuàng)建一個(gè)進(jìn)程顯然是行不通的,——無(wú)論是從系統(tǒng)資源開銷方面或是響應(yīng)用戶請(qǐng)求的效率方面來(lái)看。因此,操作系統(tǒng)中線程的概念便被引進(jìn)了。線程,是進(jìn)程的一部分,一個(gè)沒有線程的進(jìn)程可以被看作是單線程的。線程有時(shí)又被稱為輕權(quán)進(jìn)程或輕量級(jí)進(jìn)程,也是 CPU 調(diào)度的一個(gè)基本單位。
進(jìn)程的執(zhí)行過(guò)程是線狀的,盡管中間會(huì)發(fā)生中斷或暫停,但該進(jìn)程所擁有的資源只為該線狀執(zhí)行過(guò)程服務(wù)。一旦發(fā)生進(jìn)程上下文切換,這些資源都是要被保護(hù)起來(lái)的。這是進(jìn)程宏觀上的執(zhí)行過(guò)程。而進(jìn)程又可有單線程進(jìn)程與多線程進(jìn)程兩種。我們知道,進(jìn)程有 一個(gè)進(jìn)程控制塊 PCB ,相關(guān)程序段 和 該程序段對(duì)其進(jìn)行操作的數(shù)據(jù)結(jié)構(gòu)集 這三部分,單線程進(jìn)程的執(zhí)行過(guò)程在宏觀上是線性的,微觀上也只有單一的執(zhí)行過(guò)程;而多線程進(jìn)程在宏觀上的執(zhí)行過(guò)程同樣為線性的,但微觀上卻可以有多個(gè)執(zhí)行操作(線程),如不同代碼片段以及相關(guān)的數(shù)據(jù)結(jié)構(gòu)集。線程的改變只代表了 CPU 執(zhí)行過(guò)程的改變,而沒有發(fā)生進(jìn)程所擁有的資源變化。除了 CPU 之外,計(jì)算機(jī)內(nèi)的軟硬件資源的分配與線程無(wú)關(guān),線程只能共享它所屬進(jìn)程的資源。與進(jìn)程控制表和 PCB 相似,每個(gè)線程也有自己的線程控制表 TCB ,而這個(gè) TCB 中所保存的線程狀態(tài)信息則要比 PCB 表少得多,這些信息主要是相關(guān)指針用堆棧(系統(tǒng)棧和用戶棧),寄存器中的狀態(tài)數(shù)據(jù)。進(jìn)程擁有一個(gè)完整的虛擬地址空間,不依賴于線程而獨(dú)立存在;反之,線程是進(jìn)程的一部分,沒有自己的地址空間,與進(jìn)程內(nèi)的其他線程一起共享分配給該進(jìn)程的所有資源。
線程可以有效地提高系統(tǒng)的執(zhí)行效率,但并不是在所有計(jì)算機(jī)系統(tǒng)中都是適用的,如某些很少做進(jìn)程調(diào)度和切換的實(shí)時(shí)系統(tǒng)。使用線程的好處是有多個(gè)任務(wù)需要處理機(jī)處理時(shí),減少處理機(jī)的切換時(shí)間;而且,線程的創(chuàng)建和結(jié)束所需要的系統(tǒng)開銷也比進(jìn)程的創(chuàng)建和結(jié)束要小得多。最適用使用線程的系統(tǒng)是多處理機(jī)系統(tǒng)和網(wǎng)絡(luò)系統(tǒng)或分布式系統(tǒng)。
3.@protocol 和 category 中如何使用 @property
- 在protocol中使用property只會(huì)生成setter和getter方法聲明,我們使用屬性的目的,是希望遵守我協(xié)議的對(duì)象能實(shí)現(xiàn)該屬性
- category 使用 @property 也是只會(huì)生成setter和getter方法的聲明,如果我們真的需要給category增加屬性的實(shí)現(xiàn),需要借助于運(yùn)行時(shí)的兩個(gè)函數(shù):
- objc_setAssociatedObject
- objc_getAssociatedObject
4.深淺復(fù)制和屬性為copy,strong值的變化問(wèn)題
淺復(fù)制:只復(fù)制指向?qū)ο蟮闹羔槪粡?fù)制引用對(duì)象本身。對(duì)于淺復(fù)制來(lái)說(shuō),A和A_copy指向的是同一個(gè)內(nèi)存資源,復(fù)制的只不個(gè)是一個(gè)指針,對(duì)象本身資源還是只有一份,那如果我們對(duì)A_copy執(zhí)行了修改操作,那么發(fā)現(xiàn)A引用的對(duì)象同樣被修改了。深復(fù)制就好理解了,內(nèi)存中存在了兩份獨(dú)立對(duì)象本身。
在Objective-C中并不是所有的對(duì)象都支持Copy,MutableCopy,遵守NSCopying協(xié)議的類才可以發(fā)送Copy消息,遵守NSMutableCopying協(xié)議的類才可以發(fā)送MutableCopy消息。
[immutableObject copy] // 淺拷貝
[immutableObject mutableCopy] //深拷貝
[mutableObject copy] //深拷貝
[mutableObject mutableCopy] //深拷貝
屬性設(shè)為copy,指定此屬性的值不可更改,防止可變字符串更改自身的值的時(shí)候不會(huì)影響到對(duì)象屬性(如NSString,NSArray,NSDictionary)的值。strong此屬性的指會(huì)隨著變化而變化。copy是內(nèi)容拷貝,strong是指針拷貝。
5.KVO,NSNotification,delegate及block區(qū)別
KVO就是cocoa框架實(shí)現(xiàn)的觀察者模式,一般同KVC搭配使用,通過(guò)KVO可以監(jiān)測(cè)一個(gè)值的變化,比如View的高度變化。是一對(duì)多的關(guān)系,一個(gè)值的變化會(huì)通知所有的觀察者。
NSNotification是通知,也是一對(duì)多的使用場(chǎng)景。在某些情況下,KVO和NSNotification是一樣的,都是狀態(tài)變化之后告知對(duì)方。NSNotification的特點(diǎn),就是需要被觀察者先主動(dòng)發(fā)出通知,然后觀察者注冊(cè)監(jiān)聽后再來(lái)進(jìn)行響應(yīng),比KVO多了發(fā)送通知的一步,但是其優(yōu)點(diǎn)是監(jiān)聽不局限于屬性的變化,還可以對(duì)多種多樣的狀態(tài)變化進(jìn)行監(jiān)聽,監(jiān)聽范圍廣,使用也更靈活。
delegate 是代理,就是我不想做的事情交給別人做。比如狗需要吃飯,就通過(guò)delegate通知主人,主人就會(huì)給他做飯、盛飯、倒水,這些操作,這些狗都不需要關(guān)心,只需要調(diào)用delegate(代理人)就可以了,由其他類完成所需要的操作。所以delegate是一對(duì)一關(guān)系。
block是delegate的另一種形式,是函數(shù)式編程的一種形式。使用場(chǎng)景跟delegate一樣,相比delegate更靈活,而且代理的實(shí)現(xiàn)更直觀。
KVO一般的使用場(chǎng)景是數(shù)據(jù),需求是數(shù)據(jù)變化,比如股票價(jià)格變化,我們一般使用KVO(觀察者模式)。delegate一般的使用場(chǎng)景是行為,需求是需要?jiǎng)e人幫我做一件事情,比如買賣股票,我們一般使用delegate。Notification一般是進(jìn)行全局通知,比如利好消息一出,通知大家去買入。delegate是強(qiáng)關(guān)聯(lián),就是委托和代理雙方互相知道,你委托別人買股票你就需要知道經(jīng)紀(jì)人,經(jīng)紀(jì)人也不要知道自己的顧客。Notification是弱關(guān)聯(lián),利好消息發(fā)出,你不需要知道是誰(shuí)發(fā)的也可以做出相應(yīng)的反應(yīng),同理發(fā)消息的人也不需要知道接收的人也可以正常發(fā)出消息。
6.static作用?
- 函數(shù)體內(nèi) static 變量的作用范圍為該函數(shù)體,不同于 auto 變量,該變量的內(nèi)存只被分配一次,因此其值在下次調(diào)用時(shí)仍維持上次的值;
- 在模塊內(nèi)的 static 全局變量可以被模塊內(nèi)所用函數(shù)訪問(wèn),但不能被模塊外其它函數(shù)訪問(wèn);
- 在模塊內(nèi)的 static 函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用,這個(gè)函數(shù)的使用范圍被限制在聲明它的模塊內(nèi);
- 在類中的 static 成員變量屬于整個(gè)類所擁有,對(duì)類的所有對(duì)象只有一份拷貝;
- 在類中的 static 成員函數(shù)屬于整個(gè)類所擁有,這個(gè)函數(shù)不接收 this 指針,因而只能訪問(wèn)類的static 成員變量。