Delegate 作為iOS 系統中一種非常常用的設計模式,在很多地方使用的地方非常的多。
之前剛開始接觸OC 的時候,對於這個delegate模式非常的不理解,不知道這個所謂的delegate 是用來幹嘛的。
不過做了幾年的iOS開發後,對於這一塊也算是有自己的理解了。
首先 delegate 的定義是一個繼承特定介面的對象。
比如定義了如下介面:
#ifndef Protocol_h#define Protocol_h@protocol TestProtocol <NSObject>-(void)firstInterface;-(void)secondInterface;@end
然後在另外一個對象裡面,有這麼一個屬性繼承自這個介面:
#import <Foundation/Foundation.h>#import "Protocol.h"@interface TestClass : NSObject@property (nonatomic,weak) id<TestProtocol>delegate;@end
這樣的好處就像一個一把起子,對於只要符合這個起子的螺絲釘,不管是長的短的,都可以操作,因為這些螺絲釘都的介面(對應我們的 protocol)都一樣,在適當的時候可以進行替換。 所以 delegate 有一種面向抽象編程的意思,對象是不具體的但是介面是定義好的。
除此之外。 delegate 還可以做兩件事情
大家常說的delegate模式,其實也就是這個意思。不過delegate模式不是一種模式,它是兩種分別不同的功能。
第一點個就是回調。
A 有一件事情自己辦不了,要找B 幫忙辦理,辦理完之後B得把結果告訴A ,然後通過delegate 找到A。
這裡的delegate 就是A, 要得到結果,就得實現B提供的介面,這個介面是B調用A 用來告訴A結果的。
首先是類B 它是一個工具一樣的東西,能夠幫忙幹活,然後幹完活通知 讓他幹活的那個 對象,就是A
它的實現如下:
#import <Foundation/Foundation.h>@protocol ResultProtocal <NSObject>@optional-(void)addResult:(NSInteger)value;-(void)mutiplayResult:(NSInteger)value;@end@interface ObjectB : NSObject///計算兩個數之和-(void)caculateAdd:(NSInteger)a value:(NSInteger)b;///計算兩個數的乘積-(void)caculateMultiply:(NSInteger)a value:(NSInteger)b;@property (nonatomic,weak) id<ResultProtocal>delegate;@end
#import "ObjectB.h"@implementation ObjectB///計算兩個數之和-(void)caculateAdd:(NSInteger)a value:(NSInteger)b{ if (self.delegate && [self.delegate respondsToSelector:@selector(addResult:)]) { [self.delegate addResult:(a+b)]; }}///計算兩個數的乘積-(void)caculateMultiply:(NSInteger)a value:(NSInteger)b{ if (self.delegate && [self.delegate respondsToSelector:@selector(mutiplayResult:)]) { [self.delegate addResult:(a*b)]; }}@end
A 呢,A 只管讓B 幹事情就行了,但是幹完事B 得告訴A 啊,所以A得 實現函數,讓B 告訴自己結果:
A的實現如下:
#import "ObjectA.h"#import "ObjectB.h"@interface ObjectA()<ResultProtocal>@end@implementation ObjectA-(void)mainFunction{ ObjectB *b = [ObjectB new];//建立一個執行任務的對象 b.delegate = self;//告訴B 你任務完成了之後找我就行了 [b caculateAdd:100 value:200];//b 開始執行任務}/// 對象A 實現 工具B 完成任務的結果調用函數-(void)addResult:(NSInteger)value{ }-(void)mutiplayResult:(NSInteger)value{ }@end
好了這是第一種 delegate 的應用情境,看起來有一點 非同步工作的概念,事情交給你幹,結果告訴我就得了。
這也是一種面向介面的編程。 比如同一種計算方法: 不僅可以有ObjectB 也許還有ObjectD 或者 ObjectE呢,也是可以的
他們雖然都提供了計算方法,但是對於不同的情境,也許計算的實現不一樣,有的可以用二進位,有的可以用遞迴,有的可以使用
更進階的演算法等等不一而論,具有可變性。
另外一種delegate 的使用方法,有點強盜的意味。還是A 和 B 但是呢,但是呢這裡的角色得調換一下位置。
當然 A 仍然是 delegate 但是 這個時候 A 變成了幹活的那一方。
這很神奇麼。這不神奇。 這個時候,A 整合了方法,並且實現了方法,B中仍然有一個delegate對象,這個對象就是A。
下面看A代碼:
#import "ObjectA.h"#import "ObjectB.h"@interface ObjectA()@end@implementation ObjectA-(NSString*)todayIs{ return @"Friday";}-(NSString*)tomorroyIs{ return @"Saturday";}@end
再來看看B的代碼:
#import <Foundation/Foundation.h>@protocol ResultProtocal <NSObject>@optional-(NSString*)todayIs;-(NSString*)tomorroyIs;@end@interface ObjectB : NSObject@property (nonatomic,weak) id<ResultProtocal>delegate;@end
#import "ObjectB.h"@implementation ObjectB-(void)mainFunction{ /// 一開始很閑,突然想知道 今天周幾了,那好吧,讓A 告訴我 if (self.delegate && [self.delegate respondsToSelector:@selector(todayIs)]) { NSString *today = [self.delegate todayIs]; NSLog(@"%@",today); }}@end
B 搖身一遍稱為了讓A 幹活的人。。。
從代碼中可以看到 第二種情況, 定義的協議的函數實現,都有傳回值。 這是和第一種情況不一樣的地方。
而且 B 的這種調用方式,很像 同步操作。
一個delegate 兩種玩法,也挺有意思。