代理的主要組成部分:
協(xié)議:聲明委托方要代理方去處理什么事情屈嗤;
委托對象:根據(jù)指定的協(xié)議倦淀,指定代理去完成什么功能;
代理對象:根據(jù)指定的協(xié)議卒暂,完成委托方需要實現(xiàn)的功能啄栓;
三者的關系如下圖
協(xié)議委托代理三方的關系.png
可能看完這些概念還是會有些模糊。舉個簡單的例子有這樣一個需求也祠,控制器A跳轉到控制器B昙楚,在B返回到A的時候,B的某些數(shù)據(jù)需要傳遞給A處理诈嘿。這個時候B就是委托方堪旧,A就是代理方, B需要制定一個協(xié)議永淌,協(xié)議中聲明要處理數(shù)據(jù)的方法崎场。然后A要成為B的代理佩耳,去實現(xiàn)協(xié)議中聲明的方法遂蛀。
使用代理實現(xiàn)界面間的傳值(逆?zhèn)鳎?/b>
創(chuàng)建委托界面B,代碼如下:
.h文件
#import//新建一個協(xié)議干厚,協(xié)議的名稱一般是由:"類名+Delegate"@protocolViewControllerBDelegate//代理方必須實現(xiàn)的方法@required//代理方可選實現(xiàn)的方法@optional- (void)ViewControllerBsendValue:(NSString*)value;@end@interfaceViewControllerB:UIViewController//委托代理人李滴,為了避免造成循環(huán)引用,代理一般需使用弱引用@property(weak,nonatomic)id delegate;@end
.m文件
#import"ViewControllerB.h"@interfaceViewControllerB()@property(weak,nonatomic)IBOutletUITextField*textField;@property(weak,nonatomic)IBOutletUIButton*btn;@end@implementationViewControllerB- (IBAction)btnClick:(id)sender {? ? [self.navigationController popViewControllerAnimated:YES];if([_delegate respondsToSelector:@selector(ViewControllerBsendValue:)])? ? {//如果協(xié)議響應了sendValue:方法//通知代理執(zhí)行協(xié)議的方法[_delegate ViewControllerBsendValue:_textField.text];? ? }}
創(chuàng)建代理界面A:
.m文件
#import"ViewController.h"#import"ViewControllerB.h"@interfaceViewController()@end@implementationViewController- (void)viewDidLoad {? ? [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.}- (void)ViewControllerBsendValue:(NSString*)value{//創(chuàng)建一個警告框蛮瞄,來顯示從B傳過來的值UIAlertController* alerView = [UIAlertControlleralertControllerWithTitle:@"委托界面B傳過來的值"message:value preferredStyle:UIAlertControllerStyleAlert];//給警告框添加按鈕UIAlertAction*action = [UIAlertActionactionWithTitle:@"確定"style:UIAlertActionStyleDefaulthandler:^(UIAlertAction* _Nonnull action) {? ? }];? ? [alerView addAction:action];//彈出警告框[selfpresentViewController:alerView animated:YEScompletion:nil];}- (IBAction)segueBtn:(id)sender {}/**
*? 跳轉到B的時候調用
*? 作用:設置A為B的代理
*/- (void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender{//設置跳轉時的目標控制器ViewControllerB *vc = segue.destinationViewController;//設置A為B的代理vc.delegate =self;}@end
最終效果
代理逆?zhèn)髦笛菔?gif
根據(jù)上面這個例子所坯,其實我們不難發(fā)現(xiàn),代理其實就像是在委托方聲明方法挂捅,然后由代理方去實現(xiàn)芹助,從而達到傳值的效果的。
總結:
使用代理的時候,一般發(fā)送數(shù)據(jù)的一方為委托方状土,需要接收數(shù)據(jù)并對數(shù)據(jù)進行處理的一方為代理方无蜂;
委托方需要定義一個協(xié)議,還要添加代理人屬性蒙谓,只有設置了委托方的代理人屬性的類才可以成為委托方的代理斥季;關鍵代碼如下:
//新建一個協(xié)議,協(xié)議的名稱一般是由:"類名+Delegate"@protocolViewControllerBDelegate@required//代理方必須實現(xiàn)的方法@optional//代理方可選實現(xiàn)的方法,//代理方法名稱一般由:"類名+方法名"- (void)ViewControllerBsendValue:(NSString *)value;@end@interfaceViewControllerB: UIViewController//關鍵屬性委托代理人累驮,為了避免造成循環(huán)引用酣倾,代理一般需使用弱引用@property(weak,nonatomic) id delegate;@end
3.委托方通知代理方工作的代碼(給代理方傳值);
//新建一個協(xié)議谤专,協(xié)議的名稱一般是由:"類名+Delegate"@protocolViewControllerBDelegate@required//代理方必須實現(xiàn)的方法@optional//代理方可選實現(xiàn)的方法,//代理方法名稱一般由:"類名+方法名"- (void)ViewControllerBsendValue:(NSString *)value;@end@interfaceViewControllerB: UIViewController//關鍵屬性委托代理人躁锡,為了避免造成循環(huán)引用,代理一般需使用弱引用@property(weak,nonatomic) id delegate;@end
4.代理方需要設置自己成為委托方的代理毒租,也是設置委托方的delegate屬性為self稚铣,一般是在界面跳轉的時候,取到委托方的控制器墅垮,并設置的惕医。
轉自作者 @figure_ai