標籤:
Objective-C中的protocol裡存在@optional關鍵字,被這個關鍵字修飾的方法並非必須要被實現。我們可以通過介面定義一系列方法,然後由實現介面的類選擇性地實現其中幾個方法。在Cocoa API中很多情況下介面方法都是可選的,這點和Swift中的protocol的所有方法都必須被實現這一特性完全不同。
那些如果沒有實現則介面就無法正常工作的方法一般是必須的,而相對地像作為事件通知或者對非關鍵屬性進行配置的方法一般都是可選的。最好的例子我想應該是UITableViewDataSource和UITableViewDelegate。前者中有兩個必要方法:
Swift代碼
- -tableView:numberOfRowsInSection:
- -tableView:cellForRowAtIndexPath:
分別用來計算和準備tableView的高度以及提供每一個cell的樣式,而其他的像是返回section個數或者詢問 cell 是否能被編輯的方法都有預設的行為,都是可選方法;後者(UITableViewDelegate)中的所有方法都是詳細的配置和事件回傳,因此全部都是可選的。
原生的Swift protocol裡沒有可選項,所有定義的方法都是必須實現的。如果我們想要像Objective-C裡那樣定義可選的介面方法,就需要將介面本身定義為Objective-C的,也即在protocol定義之前加上@objc。另外和Objective-C中的@optional不同,我們使用沒有@符號的關鍵字optional來定義可選方法:
Swift代碼
- @objc protocol OptionalProtocol {
- optional func optionalMethod()
- }
另外,對於所有的聲明,它們的首碼修飾是完全分開的。也就是說你不能像是在Objective-C裡那樣用一個@optional指定接下來的若干個方法都是可選的了,必須對每一個可選方法添加首碼,對於沒有首碼的方法來說,它們是預設必須實現的:
Swift代碼
- @objc protocol OptionalProtocol {
- optional func optionalMethod() // 可選
- func necessaryMethod() // 必須
- optional func anotherOptionalMethod() // 可選
- }
一個不可避免的限制是,使用@objc修飾的protocol就只能被class實現了,也就是說,對於struct和enum類型,我們是無法令它們所實現的介面中含有可選方法或者屬性的。
在Swift中,如何像Objective-C定義可選介面?