概述
代理模式是一種消息傳遞方式基矮,一個完整的代理模式包括:委托對象、代理對象和協(xié)議冠场。
名詞解釋
- 協(xié)議:用來指定代理雙方可以做什么家浇,必須做什么。
- 委托對象:根據(jù)協(xié)議指定代理對象需要完成的事碴裙,即調(diào)用協(xié)議中的方法钢悲。
- 代理對象:根據(jù)協(xié)議實現(xiàn)委托方需要完成的事点额,即實現(xiàn)協(xié)議中的方法。
1.Protocol-協(xié)議
從上圖中我們可以看到三方之間的關系莺琳,在實際應用中通過協(xié)議來規(guī)定代理雙方的行為还棱,協(xié)議中的內(nèi)容一般都是方法列表,當然也可以定義屬性惭等,我會在后續(xù)文章中順帶講一下協(xié)議中定義屬性珍手。
協(xié)議是公共的定義,如果只是某個類使用辞做,我們常做的就是寫在某個類中琳要。如果是多個類都是用同一個協(xié)議,建議創(chuàng)建一個Protocol文件凭豪,在這個文件中定義協(xié)議焙蹭。遵循的協(xié)議可以被繼承,例如我們常用的UITableView嫂伞,由于繼承自UIScrollView的緣故孔厉,所以也將UIScrollViewDelegate繼承了過來,我們可以通過代理方法獲取UITableView偏移量等狀態(tài)參數(shù)帖努。
協(xié)議只能定義公用的一套接口撰豺,類似于一個約束代理雙方的作用。但不能提供具體的實現(xiàn)方法拼余,實現(xiàn)方法需要代理對象去實現(xiàn)污桦。協(xié)議可以繼承其他協(xié)議,并且可以繼承多個協(xié)議匙监,在iOS中對象是不支持多繼承的凡橱,而協(xié)議可以多繼承。
@interface TMGameViewControllerNew ()<ILVLiveAVListener,ILVLiveIMListener,AVAudioPlayerDelegate,TMGameViewModelDelegate,TMGameShowViewProcotol,TMGameControlViewDelegate,QAVChangeDelegate,CAAnimationDelegate,TMMsgTooBarDelegate,UINavigationControllerDelegate>{
NSInteger _chargeSource;
BOOL _firstComeRoom;
BOOL _firstGuideCamera;
}
2.委托對象
if ([self.delegate respondsToSelector:@selector(userLoginWithUsername:password:)]) {
// 調(diào)用代理對象的登錄方法亭姥,代理對象去實現(xiàn)登錄方法
[self.delegate userLoginWithUsername:self.username.text password:self.password.text];
}
3.代理對象
self.gameView = [[TMGameView alloc]initWithFrame:self.view.frame parentVC:self viewModel:self.gameViewModel];
self.gameView.avIsLoad = NO;
self.gameView.showView.delegate = self;
self.gameView.controlView.delegate = self;
self.gameView.msgToolBar.delegate = self;
/**
* 代理方實現(xiàn)具體登錄細節(jié)
*/
- (void)userLoginWithUsername:(NSString *)username password:(NSString *)password {
NSLog(@"username : %@, password : %@", username, password);
}
4. 代理屬性使用weak
- 首先
在我們的tableViewController中稼钩,控制器的view就是tableView,這就相當于tableViewController強引用著tableView(代理對象)
达罗。 - 然后
當我們設置delegate的時候坝撑,一般都是讓tableViewController成為代理,這個時候代理如果也使用strong粮揉,那么tableView的delegate又強引用著tableViewController巡李,所以導致循環(huán)引用,因此代理得用weak扶认! - 為什么不用assign
weak和assign是一種“非擁有關系”的指針侨拦,通過這兩種修飾符修飾的指針變量,都不會改變被引用對象的引用計數(shù)蝠引。但是在一個對象被釋放后阳谍,weak會自動將指針指向nil蛀柴,而assign則不會螃概。在iOS中矫夯,向nil發(fā)送消息時不會導致崩潰的,所以assign就會導致野指針的錯誤unrecognized selector sent to instance
吊洼。
5.代理與block對比
- 在有多個消息傳遞時训貌,用delegate實現(xiàn)更合適,看起來也更清晰冒窍。block就不太好了递沪,這個時候block反而不便于維護,而且看起來非常臃腫综液,很別扭款慨。
- 代理更加面相過程,block則更面向結(jié)果谬莹。
從設計模式的角度來說檩奠,代理更佳面向過程,而block更佳面向結(jié)果附帽。例如我們使用NSXMLParserDelegate代理進行XML解析埠戳,NSXMLParserDelegate中有很多代理方法,NSXMLParser會不間斷調(diào)用這些方法將一些轉(zhuǎn)換的參數(shù)傳遞出來蕉扮,這就是NSXMLParser解析流程整胃,這些通過代理來展現(xiàn)比較合適。而例如一個網(wǎng)絡請求回來喳钟,就通過success屁使、failure代碼塊來展示就比較好。 - 從性能上來說奔则,block的性能消耗要略大于delegate蛮寂,因為block會涉及到棧區(qū)向堆區(qū)拷貝等操作,時間和空間上的消耗都大于代理应狱。而代理只是定義了一個方法列表共郭,在遵守協(xié)議對象的objc_protocol_list中添加一個節(jié)點,在運行時向遵守協(xié)議的對象發(fā)送消息即可疾呻。