ios delegate你必須知道的事情
2012-11-06 18:18
204 查看
转载自:http://my.oschina.net/dingbuoyi/blog/69928
你開始寫iOS程式不久,應該開始面對到很多的delegate,
不管是用別人的library或是自己寫library,可能都逃不了delegate。
為了怕有些人不知道什麼是delegate,在這邊簡單的介紹一下,
delegate中文叫做委託,通常會用在class內部把一些事件處理"委託"給別人去完成。
舉個例子,XML Parser可能他知道怎麼parse xml,但是parse到的東西要怎麼處理xml parser可能不知道。
所以NSXMLParser就提供了一個NSXMLParserDelegate給client去實作,
當parse到某個element的時候,就callback delegate所定義的message,
讓他client自己去決定怎麼去處理這個element。
好吧,我承認我解釋的很模糊,不過我這篇本來就不是要你搞懂什麼是delegate,
而是針對使用或是設計delegate的時候,可能會要注意的事情。
在我們的class中設計delegate的時候,我們通常會有幾個注意事項。
假設我的class叫做MyClass,那我們可能會有定義一個MyClassDelegate這個protocol當作我的delegate protocol。
而MyClass中我們可能是這樣寫。
上面的code我們注意到
為什麼我們不用retain而要用assign呢?
原因就是在於iOS的reference counting的環境中,我們必須解決circular count的問題。
讓我們來寫寫我們平常都怎麼用delegate的,下面的code我想大家應該不陌生
這邊很快的就出現circular reference了
假設上面的code是寫在一個myViewController的物件當中,
之後一旦myViewController的reference count變成1的時候,
myViewController跟myClass這兩個兄弟兩只剩下互相retain,那就變成了孤島,也就因此造成了memory leak!!!
也因為這樣,iOS官方文件才會要建議我們所以的delegate都要用assign property。
也就是所謂"weak reference"的property,他的特色就是雖然會持有對方的reference,但是不會增加retain count。
如此下來,當myViewController的retain count變成0,則會dealloc。
同時在dealloc中,也一併把myClass release,則myClass也跟著被release。
事情就結束了嗎? 還沒有唷...
這邊還有一個大家常常忘記的重點,那就是上面的dealloc這樣寫會有潛在危險。
應該要改成這樣
你可能會很納悶,myClass不是馬上就會被release了嗎? 幹嘛要先把他的delegate設成nil?
那是因為我們假設myClass會馬上會被dealloc,但是現實狀況這個是不一定的,
有可能裡面內部有建個NSURLConnection,或是正在做某件事情而讓其他物件也retain myClass。
如果myClass沒有馬上dealloc,那他的
解決方法是在MyViewController的dealloc中,在release myClass之前,
要先把原本指向自己的delegate改設成nil,這樣才可以避免crash發生。
在我之前寫的project,很大一部份的crash都是這樣造成的,因為這個問題通常不是每次都發生,
但是發生的時候確很難在重新複製,所以不可不慎啊。
但是很興奮的是到了iOS5中的 Automatic Reference Counting這個問題可以有所改善。
在ARC中提出了一個新的weak reference的概念來取代原本的assign,
weak reference指到的物件若是已經因retain count歸零而dealloc了,則此weak reference也自動設成nil。
而原本舊的這種assign的作法,在ARC中叫做__unsafe_unretained,這只是為了相容iOS4以下的版本。
回顧重點:
如果你是寫library給別人用的,記得把你的delegate設成assign property,這樣才不會造成circular reference
當你是要始用別人的library,記得在你自己dealloc的時候,把delegate設成nil,以避免crash的事情發生。
你開始寫iOS程式不久,應該開始面對到很多的delegate,
不管是用別人的library或是自己寫library,可能都逃不了delegate。
為了怕有些人不知道什麼是delegate,在這邊簡單的介紹一下,
delegate中文叫做委託,通常會用在class內部把一些事件處理"委託"給別人去完成。
舉個例子,XML Parser可能他知道怎麼parse xml,但是parse到的東西要怎麼處理xml parser可能不知道。
所以NSXMLParser就提供了一個NSXMLParserDelegate給client去實作,
當parse到某個element的時候,就callback delegate所定義的message,
讓他client自己去決定怎麼去處理這個element。
好吧,我承認我解釋的很模糊,不過我這篇本來就不是要你搞懂什麼是delegate,
而是針對使用或是設計delegate的時候,可能會要注意的事情。
在我們的class中設計delegate的時候,我們通常會有幾個注意事項。
假設我的class叫做MyClass,那我們可能會有定義一個MyClassDelegate這個protocol當作我的delegate protocol。
而MyClass中我們可能是這樣寫。
@protocol MyClassDelegate <NSObject> - (void) myClassOnSomeEvent:(MyClass*)myClass; @end @interface MyClass { id<MyClassDelegate> _delegate; } @property (nonatomic, assign) delegate; @end
上面的code我們注意到
delegate此property是定義為
@property (assign)。
為什麼我們不用retain而要用assign呢?
原因就是在於iOS的reference counting的環境中,我們必須解決circular count的問題。
讓我們來寫寫我們平常都怎麼用delegate的,下面的code我想大家應該不陌生
- (void)someAction { myClass = [MyClass new]; myClass.delegate = self; .... }
這邊很快的就出現circular reference了
假設上面的code是寫在一個myViewController的物件當中,
之後一旦myViewController的reference count變成1的時候,
myViewController跟myClass這兩個兄弟兩只剩下互相retain,那就變成了孤島,也就因此造成了memory leak!!!
也因為這樣,iOS官方文件才會要建議我們所以的delegate都要用assign property。
也就是所謂"weak reference"的property,他的特色就是雖然會持有對方的reference,但是不會增加retain count。
如此下來,當myViewController的retain count變成0,則會dealloc。
同時在dealloc中,也一併把myClass release,則myClass也跟著被release。
- (void)dealloc { [myClass release]; [super dealloc]; }
事情就結束了嗎? 還沒有唷...
這邊還有一個大家常常忘記的重點,那就是上面的dealloc這樣寫會有潛在危險。
應該要改成這樣
- (void)dealloc { myClass.delegate = nil; [myClass release]; [super dealloc]; }
你可能會很納悶,myClass不是馬上就會被release了嗎? 幹嘛要先把他的delegate設成nil?
那是因為我們假設myClass會馬上會被dealloc,但是現實狀況這個是不一定的,
有可能裡面內部有建個NSURLConnection,或是正在做某件事情而讓其他物件也retain myClass。
如果myClass沒有馬上dealloc,那他的
myClass.delegate不就正指向一個不合法的位置了嗎? (此種pointer稱作dangling pointer)
解決方法是在MyViewController的dealloc中,在release myClass之前,
要先把原本指向自己的delegate改設成nil,這樣才可以避免crash發生。
在我之前寫的project,很大一部份的crash都是這樣造成的,因為這個問題通常不是每次都發生,
但是發生的時候確很難在重新複製,所以不可不慎啊。
但是很興奮的是到了iOS5中的 Automatic Reference Counting這個問題可以有所改善。
在ARC中提出了一個新的weak reference的概念來取代原本的assign,
weak reference指到的物件若是已經因retain count歸零而dealloc了,則此weak reference也自動設成nil。
而原本舊的這種assign的作法,在ARC中叫做__unsafe_unretained,這只是為了相容iOS4以下的版本。
回顧重點:
如果你是寫library給別人用的,記得把你的delegate設成assign property,這樣才不會造成circular reference
當你是要始用別人的library,記得在你自己dealloc的時候,把delegate設成nil,以避免crash的事情發生。
相关文章推荐
- ios delegate你必須知道的事情
- ios delegate你必须知道的事情
- ios delegate你必须知道的事情
- 关于IOS中的delegate必须知道的事情
- ios delegate你必须知道的事情
- ios delegate你必须知道的事情
- ios必须知道的事情
- IOS中UIview需要知道的一些事情:setNeedsDisplay、setNeedsLayout
- 『IOS』UIview需要知道的一些事情:setNeedsDisplay、setNeedsLayout
- 学习iOS前我们需要知道的事情
- IOS开发-需要知道的一些事情
- 『iOS』UIview需要知道的一些事情:setNeedsDisplay、setNeedsLayout
- 有些星座天生不适合干有些事情,如果一定要为之恐怕就会落到饿死的地步了!你知道自己这个星座有哪些事情是容易让自己饿死的吗?
- 【iOS知识学习】_协议(delegate)和类别(category)
- IOS开发UI控件<UITableView>和Delegate的使用
- AVAudioPlayer和AVAudioPlayerDelegate-iOS音频播放器
- 3. NHibernate基础知识 - 你必须知道的一些事情
- 每一个C#开发者必须知道的13件事情
- 关于女人 男人应该偷偷知道的十件事情
- 你应该知道的10件关于Java 6的事情