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ù)減一.