iOS之內(nèi)存管理

objc中,與alloc語義相反的方法是dealloc還是release?與retain語義相反的方法是dealloc還是

release,為什么?需要與alloc配對使用的方法是dealloc還是release,為什么?

答:alloc與dealloc語意相反,alloc是創(chuàng)建變量,dealloc是釋放變量。retain對應(yīng)release,retain保留一個對象。調(diào)用之后,變量的計數(shù)加1?;蛟S不是很明顯,在這有例為證:

- (void) setname : (nsstring*) name {

[name retain];

[myname release];

myname = name;

}我們來解釋一下:設(shè)想,用戶在調(diào)用這個函數(shù)的時候,他注意了內(nèi)存的管理,所以他小心的寫了如下代碼:

nsstring * newname = [[nsstring alloc] initwithstring:@"john"];

[aclass setname: newname];

[newname release];

我們來看一看newname的計數(shù)是怎么變化的。首先,它被 alloc,count = 1;然后,在setname中,它被retain,count = 2; 最后,用戶自己釋放newname,count=1,myname指向了newname。這也解釋了為什么需要調(diào)用[mynamerelease]。我們需要在給myname賦新值的時候,釋放掉以前老的變量。retain之后直接dealloc對象計數(shù)器沒有釋放。alloc需要與release配對使用,因為alloc這個函數(shù)調(diào)用之后,變量的計數(shù)加1。所以在調(diào)用alloc之后,一定要調(diào)用對應(yīng)的release。另外,在release一個變量之后,他的值仍然有效,所以最好是后面緊接著再var= nil。

在一個對象的方法里面:self.name = “object”;和name =”object”有什么不同嗎?

答:self.name = "object"會調(diào)用對象的setname()方法,name ="object"會直接把object賦值給當(dāng)前對象的name 屬性。

這段代碼有什么問題嗎:

@implementation person

- (void)setage:(int)newage {

self.age = newage;

}

@end

答:會進(jìn)入死循環(huán)。

什么是retain count?

答:引用計數(shù)(ref count或者retaincount)。對象的內(nèi)部保存一個數(shù)字,表示被引用的次數(shù)。例如,某個對象被兩個指針?biāo)赶颍ㄒ茫┠敲此膔etaincount為2需要銷毀對 象的時候,不直接調(diào)用dealloc,而是調(diào)用release。release會 讓retaincount減1,只有retain count等于0,系統(tǒng)才會調(diào)用dealloc真正銷毀這個對象。

以下每行代碼執(zhí)行后,person對象的retain count分別是多少?

person *person = [[person alloc] init];

count 1[person retain];

count 2[person release];

count 1[person release];

retain count = 1;

為什么很多內(nèi)置類如uitableviewcontroller的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。當(dāng)a不再使用b,調(diào)用release釋放對b的所有權(quán),因為c還引用了b,所以b的引用計數(shù)為1,b不會被釋放。b不釋放,c的引用計數(shù)就是1,c也不會被釋放。從此,b和c永遠(yuǎn)留在內(nèi)存中。

這種情況,必須打斷循環(huán)引用,通過其他規(guī)則來維護(hù)引用關(guān)系。我們常見的delegate往往是assign方式的屬性而不是retain方式的屬性,賦值不會增加引用計數(shù),就是為了防止delegation兩端產(chǎn)生不必要的循環(huán)引用。如果一個uitableviewcontroller對象a通過retain獲取了uitableview對象b的所有權(quán),這個uitableview對象b的delegate又是a,如果這個delegate是retain方式的,那基本上就沒有機(jī)會釋放這兩個對象了。自己在設(shè)計使用delegate模式時,也要注意這點。

定義屬性時,什么情況使用copy,assign,和retain 。

答:assign用于簡單數(shù)據(jù)類型,如nsinteger,double,bool,retain 和copy用戶對象,copy用于當(dāng)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){

[propertyrelease];

property=[newvalueretain];

}

autorelease的對象是在什么時候被release的?

答:autorelease實際上只是把對release的調(diào)用延遲了,對于每一個autorelease,系統(tǒng)只是把該object放入了當(dāng)前的autoreleasepool中,當(dāng)該pool被釋放時,該pool中的所有object會被調(diào)用release。對 于每一個runloop,系統(tǒng)會隱式創(chuàng)建一個autorelease pool,這樣所有的releasepool會構(gòu)成一個象callstack一樣的一個棧式結(jié)構(gòu),在每一個runloop結(jié)束時,當(dāng)前棧頂?shù)腶utoreleasepool會被銷毀,這樣這個pool里的每個object(就是autorelease的對象)會被release。那什么是一個runloop呢?一個ui事件,timer call, delegate call, 都會是一個新的runloop。那什么是一個runloop呢?一個ui事件,timer call, delegate call, 都會是一個新的runloop。

這段代碼有什么問題,如何修改

for (int i = 0; i < somelargenumber; i++){

nsstring *string = @”abc”;

string = [string lowercasestring];

string = [string stringbyappendingstring:@"xyz"];

nslog(@“%@”, string);

}

答:會內(nèi)存泄露,

for(inti =0;i<1000;i++)

{ nsautoreleasepool* pool1 =[[nsautoreleasepoolalloc]init];

nsstring*string =@"abc";

string = [stringlowercasestring];

string =[stringstringbyappendingstring:@"xyz"];

nslog(@"%@",string);

[pool1drain];

}

什么是notification?

答:觀察者模式,controller向defaultnotificationcenter添加自己的notification,其他類注冊這個notification就可以收到通知,這些類可以在收到通知時做自己的操作(多觀察者默認(rèn)隨機(jī)順序發(fā)通知給觀察者們,而且每個觀察者都要等當(dāng)前的某個觀察者的操作做完才能輪到他來操作,可以用notificationqueue的方式安排觀察者的反應(yīng)順序,也可以在添加觀察者中設(shè)定反映時間,取消觀察需要在viewdidunload 跟dealloc中都要注銷)。

什么時候用delegate,什么時候用notification?

答:delegate針對one-to-one關(guān)系,并且reciever可 以返回值給sender,notification可以針對one-to-one/many/none,reciever無法返回值給sender.所以,delegate用于sender希望接受到reciever的某個功能反饋值,notification用于通知多個object某個事件。

什么是kvc和kvo?

答:kvc(key-value-coding)內(nèi)部的實現(xiàn):一個對象在調(diào)用setvalue的時候,(1)首先根據(jù)方法名找到運行方法的時候所需要的環(huán)境參數(shù)。(2)他會從自己isa指針結(jié)合環(huán)境參數(shù),找到具體的方法實現(xiàn)的接口。(3)再直接查找得來的具體的方法實現(xiàn)。kvo(key-value-observing):當(dāng)觀察者為一個對象的屬性進(jìn)行了注冊,被觀察對象的isa指針被修改的時候,isa指針就會指向一個中間類,而不是真實的類。所以isa指針其實不需要指向?qū)嵗龑ο笳鎸嵉念?。所以我們的程序最好不要依賴于isa指針。在調(diào)用類的方法的時候,最好要明確對象實例的類名。

ViewController 的 loadView, viewDidLoad, viewDidUnload

分別是在什么時候調(diào)用的?在自定義ViewController的時候這幾個函數(shù)里面應(yīng)該做什么工作?

答:viewDidLoad在view從nib文件初始化時調(diào)用,loadView在controller的view為nil時調(diào)用。此方法在編程實現(xiàn)view時調(diào)用,view控制器默認(rèn)會注冊memory warning notification,當(dāng)view controller的任何view沒有用的時候,viewDidUnload會被調(diào)用,在這里實現(xiàn)將retain 的viewrelease,如果是retain的IBOutlet view 屬性則不要在這里release,IBOutlet會負(fù)責(zé)release。

自動釋放池是什么,如何工作?

當(dāng)您向一個對象發(fā)送一個autorelease消息時,Cocoa就會將該對象的一個引用放入到最新的自動釋放池。它仍然是個正當(dāng)?shù)膶ο螅虼俗詣俞尫懦囟x的作用域內(nèi)的其它對象可以向它發(fā)送消息。當(dāng)程序執(zhí)行到作用域結(jié)束的位置時,自動釋放池就會被釋放,池中的所有對象也就被釋放。

1.ojc-c 是通過一種"referringcounting"(引用計數(shù))的方式來管理內(nèi)存的,對象在開始分配內(nèi)存(alloc)的時候引用計數(shù)為一,以后每當(dāng)碰到有copy,retain的時候引用計數(shù)都會加一,每當(dāng)碰到release和autorelease的時候引用計數(shù)就會減一,如果此對象的計數(shù)變?yōu)榱?, 就會被系統(tǒng)銷毀.2.NSAutoreleasePool 就是用來做引用計數(shù)的管理工作的,這個東西一般不用你管的.3.autorelease和release沒什么區(qū)別,只是引用計數(shù)減一的時機(jī)不同而已,autorelease會在對象的使用真正結(jié)束的時候才做引用計數(shù)減一.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容