iOS代理模式
代理模式:一個對象讓另一個對象替他執行一定的動作。
就是你想做一件事但不想自己去做,你就需要制定一個代理,讓這個代理幫忙去做,體現在代碼上就是聲明一個代理對象作為成員變數。需要作某些事情的時候調用該代理對象的方法。
下面的例子是住人想看電影需要知道電影票的相關資訊,但是主人很懶,需要讓僕人幫忙去搜集相關的資訊將結果告訴住人。
Person.h
@interface Person : NSObject@property (nonatomic,strong) Servant * delegate;- (void) buyTicket;@end
Person.m
@implementation Person- (void) buyTicket{ NSLog(@"票價為%d的票還剩餘%d張",[_delegate ticketprice],[_delegate leftTicketCount]);}@end
Servant.h
@interface Servant : NSObject- (int) ticketprice;- (int) leftTicketCount;@end
Servant.m
@implementation Servant- (int)ticketprice{ //..... return 1;}- (int)leftTicketCount{ //..... return 1000;}@end
Main
int main(int argc, const char * argv[]){ Person *p = [[Person alloc] init]; Servant *s = [[Servant alloc]init]; p.delegate = s; [p buyTicket]; return 0;}
列印:票價為1的票還剩餘1000張
上面的代碼雖然實現了這個功能,但是存在的問題是代碼之間的耦合性太高。如果Servant類改變了,相應的需要修改Person類的內容。在iOS中通過協議實現代理。
想要減弱代碼的耦合性,首先考慮Person類中聲明的代理對象指標為萬能指標而不是僅僅局限於限定某種類型的類,這樣修改代理的類就不需要更改本類的內容。
即下面的代碼聲明
@property (nonatomic,strong) Servant * delegate;
改為
@property (nonatomic,strong) id delegate;
顯然這樣會導致Person.m類中的方法調用出錯,因為_delegate成員是id類型的,編譯器不知道他的方法有哪些。
因此可以將這兩個方法抽成協議,在聲明代理變數的時候限定其需要實現該協議,這樣就不會報方法找不到的錯誤了,即:
@property (nonatomic,strong) id delegate;
Person.h
@interface Person : NSObject@property (nonatomic,strong) id delegate;- (void) buyTicket;@end
TicketDelegate.h
@protocol TicketDelegate @required- (int) ticketprice;- (int) leftTicketCount;@end
Servant1.h
//Servant1類實現TicketDelegate協議@interface Servant1 : NSObject < TicketDelegate >@end
Servant1.m
@implementation Servant1- (int)ticketprice{ //..... return 1;}- (int)leftTicketCount{ //..... return 1000;}@end
這樣,當需要更換代理的時候就不需要修改Person類裡面的代理對象的的聲明,減少代碼之間的耦合度。另外,目前感覺代理和回調有很大的相似之處,只是關注的角度不一樣。