1. 程式人生 > >iOS中的delegate的用法和規範

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

delegate掛鉤

參考文件