iOS設計模式之二:Delegate模式

代理模式 顧名思義就是委託別人去做事情。

iOS中經常會遇到的兩種情況:在cocoa框架中的Delegate模式與自定義的委託模式。下面分別舉例說明一下:

一、cocoa框架中的delegate模式

在cocoa框架中的Delegate模式中,委託人往往是框架中的對象(視圖中的控件、表視圖神馬的),代理人往往是視圖控制器對象。

在我們這個例子中UITableView是委託人,代理人首先得滿足一個條件:就是在.h文件中申明它擁有代理資格:

@interface WhateverViewController <<span style="color:#ff0000;">UITableViewDelegate</span>>
@end

紅色的表示這個視圖控制器擁有UITableView的代理資格。

其次,在.m文件中定義委託人可以讓代理人去代替做的事情:

//視圖控制器來代辦應該有多少個節
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [NSArray count];
}

//視圖控制器來代辦某個節應該有多少行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [[NSArray objectAtIndex:section]count];
}
// 視圖控制器來代辦負責每個欄格的外觀
- (UITableViewCell *)tableView:(UITableView *)tableView 
      cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 
    static NSString *CellIdentifier = @"Cell";
 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                reuseIdentifier:CellIdentifier] autorelease];
    }
 
    cell.textField.text = [NSArray objectAtIndex:indexPath.row]; 
 
    return cell;
}
//負責當欄格被點擊後需要觸發的事件
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    AnotherViewController *anotherViewController = [[AnotherViewController alloc]
                                                                         initWithNibName:@"AnotherView" bundle:nil];
    [self.navigationController pushViewController:anotherViewController];
    [anotherViewController release];
}
// 這個是可選的,視圖控制器勤快我就幫你代辦,不勤快我就可以不幫你辦這事兒,(提供哪些個行可以被編輯)
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}

// 對特定編輯風格進行操作
- (void)tableView:(UITableView *)tableView 
        commitEditingStyle:(UITableViewCellEditingStyle)editingStyle 
        forRowAtIndexPath:(NSIndexPath *)indexPath 
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
    }
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
    }
}

// 可選,對那些被移動欄格作特定操作
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath 
        toIndexPath:(NSIndexPath *)toIndexPath {
}

// 對那些可以移動的行返回YES
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    // 如果不想讓欄格移動,就返回NO
    return YES;
}

好了,當這個委託人需要辦這些事時,代理人自己就站出來幫忙辦了。這就是ios中的Delegate模式。

二、自定義的delegate模式

@interface A:UIView
id transparendValueDelegate;
@property(nomatic, retain) id transparendValueDelegate;

@end

@implementation A
@synthesize transparendValueDelegate

-(void)Call
{ 
NSString* value = @"你好";
[transparendValueDelegate transparendValue: value];
}

@end

@interface B:UIView
NSString* value;
@end


@implementation B
-(void)transparendValue:(NSString*)fromValue
{
value = fromValue;
NSLog(@"%@ ,我是B",value); 
}
@end

使用時:
A* a = [[A alloc] init];
B* b = [[B alloc] init];
a. transparendValueDelegate = b;//設置A代理委託對象爲B
[a Call];

這樣就會輸出:

你好,我是B

委託模式關鍵就在於一個“被”字。這個B是很被動的,隨時就會被你A Call一下。

 

三、爲什麼會有delegate模式

換句話說,它可以用來解決神馬問題?

當一個類的某些功能需要被別人來實現,但是既不明確是些什麼功能,又不明確誰來實現這些功能的時候,委託模式就可以派上用場。

例如你可以再寫個C類,實現

-(void)transparendValue:(NSString*)fromValue {
	NSLog(@"%@ ,我是C",value); 
}
也是完全可以的。換誰來,只要它實現了這個方法,我就可以委託它來做這個事。

說到底一切都是爲了使類之間的耦合性更鬆散。好的代碼應該對擴展開放,對修改關閉

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章