1四、block與代理的對比

block 和 delegate 均可以通知外面。block 更輕型,使用更簡單,可以直接訪問上下文,這樣類中不須要存儲臨時數據,使用 block 的代碼一般會在同一個地方,這樣讀代碼也連貫。delegate 更重一些,須要實現接口,它的方法分離開來,不少時候須要存儲一些臨時數據,另外相關的代碼會被分離到各處,沒有 block 好讀。swift

應該優先使用 block。而有兩個狀況能夠考慮 delegate。數組

1. 有多個相關方法。假如每一個方法都設置一個 block, 這樣會更麻煩。而 delegate 讓多個方法分紅一組,只須要設置一次,就能夠屢次回調。當多於 3 個方法時就應該優先採用 delegate。緩存

好比一個網絡類,假如只有成功和失敗兩種狀況,每一個方法能夠設計成單獨 block。但假如存在多個方法,好比有成功、失敗、緩存、https 驗證,網絡進度等等,這種狀況下,delegate 就要比 block 要好。安全

在 swift 中,利用 enum, 多個方法也能夠合併成一個 block 接口。swift 中的枚舉根據狀況不一樣,能夠關聯不一樣數據類型。而在 objc 就不建議這樣作,objc 這種狀況下,額外數據須要使用 NSObject 或者 字典進行強轉,接口就不夠安全。網絡

2. 爲了不循環引用,也可使用 delegate。使用 block 時稍微不注意就造成循環引用,致使對象釋放不了。這種循環引用,一旦出現就比較難檢查出來。而 delegate 的方法是分離開的,並不會引用上下文,所以會更安全些。動畫

假如寫一個庫供他人使用,不清楚使用者的水平如何。這時爲防止誤用,寧願麻煩一些,笨一些,使用 delegate 來替代 block。設計

將 block 簡單分類,有三種情形。對象

* 臨時性的,只用在棧當中,不會存儲起來。
好比數組的 foreach 遍歷,這個遍歷用到的 block 是臨時的,不會存儲起來。接口

* 須要存儲起來,但只會調用一次,或者有一個完成時期。
好比一個 UIView 的動畫,動畫完成以後,須要使用 block 通知外面,一旦調用 block 以後,這個 block 就能夠刪掉。事件

* 須要存儲起來,可能會調用屢次。
好比按鈕的點擊事件,假如採用 block 實現,這種 block 就須要長期存儲,而且會調用屢次。調用以後,block 也不能夠刪除,可能還有下一次按鈕的點擊。

對於臨時性的,只在棧中使用的 block, 沒有循環引用問題,block 會自動釋放。而只調用一次的 block,須要看內部的實現,正確的實現應該是 block 調用以後,立刻賦值爲空,這樣 block 也會釋放,一樣不會循環引用。

而屢次調用時,block 須要長期存儲,就很容易出現循環引用問題。

Cocoa 中的 API 設計也是這樣的,臨時性的,只會調用一次的,採用 block。而屢次調用的,並不會使用 block。好比按鈕事件,就使用 target-action。有些庫將按鈕事件從 target-action 封裝成 block 接口, 反而容易出問題。
相關文章
相關標籤/搜索