iOS中的delegate的用法和規範
delegate是Objective-C編寫的應用中各種物件之間互相呼叫的主要方式之一. 通常情況下, 物件可以接收的訊息都通過在介面檔案中宣告的方法來表示.
@protocol MyProtocol <NSObject>
- (void)func;
@end
- 1
- 2
- 3
什麼是 delegate
delegate是委託模式.委託模式是將一件屬於委託者做的事情,交給另外一個被委託者來處理.
一個標準的委託由以下部分組成:
協議的宣告
我們需要用協議來申明哪些方法是被委託出去了.
@protocol MyUIViewDelegate <NSObject> - (void)func; @end
- 1
- 2
- 3
委託者申明一個屬性
委託者裡得有一個屬性代表被委託者, 注意這個屬性是弱引用.
@interface MyUIView: UIView
@property(nonatomic, weak) id<MyUIViewDelegate> delegate;
- 1
- 2
被委託者宣告實現了協議
被委託者需要宣告自己實現了委託裡的協議.
@interface MyUIViewController : UIViewController <MyUIViewDelegate>
@end
- 1
- 2
設定委託
在被委託者裡設定自己是委託者的被委託者.嘛,這句話是有些繞.
// viewcontroller. m中
- (id)init
{
MyUIView *myView = [[MyUIView alloc] init]; //對MyUIView進行初始化
myView.delegate = self; // 將MyUIViewController自己的例項作為委託物件
self.view = myView;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
委託事件
在委託者裡呼叫委託的方法.
// MyUIView.m中
- (void)doSomething
{
[self.delegate func];
}
- 1
- 2
- 3
- 4
- 5
delegate的用途
委託一般可以分成3種
傳遞事件
傳遞事件就是A發生了什麼事情, 希望B知道下, 然後B在自己的類裡面要做出某些反應.典型的如 tableView:didSelectRowAtIndexPath:
, 就是UITableView點選了某個cell的時候, 希望其它類(通常是ViewController)響應這個點選, 在點選的時候跳轉到其他viewController之類的.
確定事件可執行
確定事件可執行是當A需要執行某個事件的時候, A不確定到底可執行, 這個時候希望B能迴應下. 如tableView:shouldHighlightRowAtIndexPath:
是UITableView詢問其它類要不要高亮顯示某個cell, 當返回NO的時候, 就UITableView就不會執行cell的高亮方法.
傳遞值
傳遞值是當A需要某個資料的時候, 由B來提供. 例子還是UITableView裡的,tableView:cellForRowAtIndexPath:
是需要某個cell的時候由其他類提供這個cell.
委託命名
委託
通常的委託用delegate做字尾.如<UIScrollViewDelegate>
@protocol <#class#>Delegate
- 1
資料來源
當你的委託的方法過多, 可以拆分資料部分和其他邏輯部分, 資料部分用dataSource做字尾. 如<UITableViewDataSource, UITableViewDelegate>
@protocol <#class#>DataSource
- 1
方法修飾
委託的方法不是百分百必須實現的.
必須實現的方法
用required修飾的方法是必須實現的.協議預設宣告在其中的方法為必須實現的方法.
@protocol MyProtocol <NSObject>
@required
- (void)func;
@end
// 用的時候
- (void)doSomething
{
[_delegate <#func2#>];
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
可以實現的方法
用optional修飾的方法可以不實現. 在用到的時候需要先判斷方法是否存在
@protocol MyProtocol <NSObject>
@optional
- (void)func;
@end
// 用的時候
- (void)doSomething
{
if (_delegate respondsToSelector:@selector(<#func2#>))
{
[_delegate <#func2#>];
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
方法命名
當特定的事件發生時, 物件會觸發它註冊的委託方法.
委託的方法, 第一個引數是觸發它的物件,第一個關鍵詞是觸發物件的類名, 錯誤的狀態必須帶有error資訊, 其他的引數看實際情況. 根據委託方法觸發的時機和目的, 使用should,will,did等關鍵詞.更具事件的狀態, 使用finish, fail, start等關鍵詞.
- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row;
- 1
完成
finish表示一個事件已經完成, 通常情況下我們預設是成功.
- (void)<#class#>DidFinish<#event#>:(id)class
- 1
失敗
fail表示一個事件已經失敗了, 我們在這裡需要返回錯誤的原因.
- (void)<#class#>:(id)class didFail<#event#>:(NSError *)error
- 1
開始
start標誌一個事件的開始.
- (void)<#class#>DidStart<#event#>:(id)class
- 1
將要開始
should表示某事件將要開始.同意開始則返回YES, 否則返回NO
- (BOOL)<#class#>ShouldStart<#event#>:(id)class
- 1
多播委託
通常的委託只支援一對一的委託, 但是在某些場景下, 我們希望有多個被委託者. 這種場景下可以考慮使用多播委託.
每個多播委託的委託者類建議有以下的基本描述
// .h
// 多播委託, 建議加上你的協議修飾: -(id <InAppPurchasesServiceProtocol>)multicastDelggate;
- (id)multicastDelggate;
- (void)addDelegate:(id)delegate;
- (void)removeDelegate:(id)delegate;
- (void)removeAllDelegates;
- 1
- 2
- 3
- 4
- 5
- 6
實現檔案裡, 你需要這麼寫
// .m
- (void)addDelegate:(id)delegate
{
[_multicastDelggate addDelegate:delegate delegateQueue:dispatch_get_main_queue()];
}
- (void)removeDelegate:(id)delegate
{
[_multicastDelggate removeDelegate:delegate];
}
- (void)removeAllDelegates
{
[_multicastDelggate removeAllDelegates];
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
其他的用法和普通的delegate類似
// 協議
@protocol InAppPurchasesServiceProtocol <NSObject>
@optional
/**
* @brief callback for update product list succeed
*/
-(void)inAppPurchasesService:(InAppPurchasesService *)service didUpdatedProducts:(NSArray *)array;
// 用的時候
[self.multicastDelggate inAppPurchasesService:self didUpdatedProductsFailed:error];
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11