在ios開發中,我們經常會用到類似如下的對話框:
因此,如下這段代碼我們也就很熟悉了:
- (IBAction)showSheet:(id)sender { UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"title,nil時不顯示" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"確定" otherButtonTitles:@"第一項", @"第二項",nil]; actionSheet.actionSheetStyle = UIActionSheetStyleBlackOpaque; [actionSheet showInView:self.view]; }其中initWithTitle函數的第二個參數為delegate,那麼是什麼呢? 我們到它的頭文件中看看。initWithTitle這個函數的聲明如下 :
- (id)initWithTitle:(NSString *)title delegate:(id是的,上面這個巨長無比的函數聲明就是initWithTitile函數,oc這個語言本身給我的感覺就是繁雜。廢話不多說,我們直接看到delegate參數的類型是id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle destructiveButtonTitle:(NSString *)destructiveButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION;
@protocol UIActionSheetDelegate可以看到UIActionSheetDelegate是一個普普通通的協議,在@optional下面有六個函數,這些函數都是可選實現的,每個函數對應的是UIActionSheet中每個按鈕的點擊事件處理,當然最後兩個函數是按照索引來區分Button對象的。@optional // Called when a button is clicked. The view will be automatically dismissed after this call returns - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex; // Called when we cancel a view (eg. the user clicks the Home button). This is not called when the user clicks the cancel button. // If not defined in the delegate, we simulate a click in the cancel button - (void)actionSheetCancel:(UIActionSheet *)actionSheet; - (void)willPresentActionSheet:(UIActionSheet *)actionSheet; // before animation and showing view - (void)didPresentActionSheet:(UIActionSheet *)actionSheet; // after animation - (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex; // before animation and hiding view - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex; // after animation @end
協議與delegate不是同一概念,協議是語言級別的特性,而delegate是借助協議來的實現的一種設計模式,其實就是代理模式。通過注入代理對象實現相應的功能。其實它的主要功能也就是實現回調,與Java中的listener一樣。
下面以一個示例來說明 :
// ButtonClickDelegate協議 @protocol ButtonClickDelegatemain函數:-(void) onClick: (id) sender ; @end // view的聲明,實現了ButtonClickDelegate協議 @interface UIView : NSObject { @protected id clickDelegate ; } // 點擊事件代理,因此UIView實現了ButtonClickDelegate協議,因此自己可以為自己代理。 @property (nonatomic, strong) id clickDelegate ; // 點擊view的觸發函數 -(void) performClick ; @end // view的實現 @implementation UIView @synthesize clickDelegate ; // 默認的點擊事件 -(id) init { self = [super init] ; if ( self ) { clickDelegate = self ; } return self; } // 點擊view的事件的默認處理 -(void) onClick: (id) sender { NSLog(@"點擊view的默認處理函數.") ; } // 點擊事件 -(void) performClick { [clickDelegate onClick: self ] ; } @end // ViewController聲明, 實現了ButtonClickDelegate協議,可以作為UIView的代理 @interface ViewController : NSObject @property (nonatomic, strong) UIView* parenView ; @end // ViewController實現 @implementation ViewController -(void) onClick:(id)sender { NSLog(@"ViewController來實現點擊事件") ; } @end
// main int main(int argc, const char * argv[]) { @autoreleasepool { // view對象 UIView* view = [[UIView alloc] init] ; [view performClick] ; // 構建一個ViewController對象 ViewController* controller = [[ViewController alloc] init] ; view.clickDelegate = controller ; [view performClick] ; } return 0; }
首先創建了一個UIView對象view, 然後調用performClick函數,此時view沒有設置delegate,但是由於自己實現了ButtonClickDelegate協議,因此可以為自己代理該點擊事件。然後我們創建了ViewController對象controller, 並且將該對象設置為view對象的delegate, 然後執行performClick函數,此時在performClick函數中
會執行ViewController中的onClick函數,即controller代理了view的點擊事件處理。輸出結果如下 :
點擊view的默認處理函數. ViewController來實現點擊事件
delegate與Java中的Listener的功能大致是相同的,比如我們看看Android中一個按鈕的點擊事件的處理。
Button mJumpButton = (Button) findViewById(R.id.button_jump); mJumpButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, SecondActivity.class); startActivity(intent); } });
其中的Button就相當於上文中的UIView,而其setOnClickListener就相當於delegate屬性的設置方法,OnClickListener就扮演了上文中ButtonClickDelegate的角色,
onClick方法更是如出一轍。其實每個平台大體上的設計思路也都是很相近的,觀察不同平台的對比實現更容易理解吧。
// 點擊事件代理,因此UIView實現了ButtonClickDelegate協議,因此自己可以為自己代理。 @property (nonatomic, strong) idclickDelegate ;
注意這裡的類型是id
void setData(List extends Order> myorders) ;在setData函數中接受的參數為元素類型為Order子類的List集合,與id