首先,協議(protocol)不是對象,是Objective-C的一種語法,用于聲明一組方法,約定調用者可以使用實現者的哪些方法。
協議不能被單獨實例化,隻能由類來明文聲明,并具體實現。
用Xcode8添加協議
基本步驟與iOS開發基礎:如何使用類别(Category) 相似,隻是文件類型選擇協議:
協議聲明:
@optional
表示實現者可自由選擇是否實現;
@required
表示必須實現。
聲明繼承協議:
協議不但可以繼承的,并且可以多繼承,在尖括号中用逗号分隔:
這裡NSObject
是個協議名,并不是類名。如果實現者聲明XSProtocol
,則需要同時實現NSObject
, NSCopying
兩套協議。
協議的實現:
如我們常用的UITableView的數據源和代理,可以用同一個類來實現:
在@implementation
部分,實現協議聲明的方法:
編譯器會告訴你哪些必要的(聲明為@required
的)協議方法沒有實現:
協議的使用:
1. 指定對象需要實現的方法:
一看這樣的聲明,就知道該方法需要一個會編程的學生,
如果傳入一個普通的Student對象,會引發一個警告:
所以協議可以幫助我們寫出自我說明的代碼,并且編譯器會幫助我們檢查。
2. 調用時,先判斷被調用者是否實現某方法:
可能有些童鞋會想,每次調用方法前(即使不是協議方法)都調用一次respondsToSelector,不就萬無一失了嗎?很不幸,respondsToSelector會消耗較多的資源,降低程序的執行效率,因此建議新手在調用協議方法時必須進行檢查,等經驗積累後,再根據具體需要自行選擇是否檢查,比如需要提高性能時,可以緩存respondsToSelector的判斷結果。
什麼是代理?
代理(delegate)是A對象指定B對象處理某些特定任務的設計模式,這裡B對象就成為了A對象的“代理”。
在Objective-C中,協議是實現代理模式的一種方式,
協議提供了面向接口編程的一種方式,使用協議,調用者隻需關心被調用者是否能做某事,而不關心被調用者具體是誰。
這就是為什麼代理對象總是被聲明成id
,也就是說,隻要實現了協議,任何類都可以成為代理。
理解了代理模式,這裡需要提醒使用協議的一個注意點:
聲明為代理的屬性,需要定義為 weak
因為B将自己聲明為A的代理,必然也會保留A,這樣相互保留的關系很容易形成“保留環”,造成内存無法釋放。
小結
協議是Objective-C 的一種語法,聲明了一套方法,而代理是一種設計模式,可以用協議來實現。
使用協議要注意三個問題:
-
指定對象需要實現的方法。
-
調用時,先判斷被調用者是否實現某方法。
-
聲明為代理的屬性,需要定義為 weak。