事實證明, 這樣的確是可以運作, 連個編譯的錯誤訊息都沒有。當使用者點選了 UIAlertView 上的按鈕時, 的確會引發 clickedButtonAtIndex。@interface ViewController : UIViewController
....
- (void)alertView:(UIAlertView *)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex {
.....
}
@end
但若是使用 UIActionSheet 時, 書中卻又強調委派物件必須遵守 UIActionSheetDelegate 協定。因此, 如果一樣由 controller 擔任委派物件時, controller 類別大概會長這樣:
實在覺得很奇怪, 兩個元件的 pattern 其實是一樣的, 但為甚麼一個需要明確標示遵守協定, 另一個卻不用?經過 google 找到這一篇 Why do I not need to declare UIAlertViewDelegate in the header?, 看起來原因有兩個:@interface ViewController :
UIViewController<UIActionSheetDelegate>
.....
- (void)actionSheet:(UIActionSheet *)actionSheet
clickedButtonAtIndex:(NSInteger)buttonIndex {
.....
}
@end
- 在建立 UIAlertView 的 initXXX 方法中, delegate: 的型態是 delegate:(id), 並沒有要求委派物件必須遵守任何協定。但是在建立 UIActionSheet 的 initXXX 方法中, delegate: 的型態卻是 delegate:(id < UIActionSheetDelegate >), 表示委派物件應該要遵守 UIActionSheetDelegate 協定。
- 在 Objective-C 中, 協定的角色似乎沒有其他種類物件導向語言中的界面 (Interface) 那樣嚴謹。事實上, 如果擔任 UIActionSheet 的委派物件並沒有遵守 UIActionSheetDelegate 協定, 只要實作有正確的 clickedButtonAtIndex: 方法, 程式一樣可以動, 只是編譯時會有警告訊息而已。而在 framework 的實作中, 看來也都是以透過
respondsToSelector:@selector(delegatedMethod:)
檢查委派物件是否具有指定的方法, 才會實際叫用該方法, 而不是依靠是否遵循特定的協定來判斷。
沒有留言:
張貼留言