前言
大学四年好快就过去了,毕业之前去公司实习,发现了自己对代理的一些概念还不理解,遂写了这篇文章。
关于 protocol & delegate
iOS 的 protocol 和 Android 的有一些不一样,因为 iOS 没有多继承,所以很多时候都是用 protocol 来实现。
而 delegate 是一种代理的模式,他相当于一个人把一些事情代理给其他人做。比如 A 控制器中有一个值是基于代理方法而改变的,当我们从 A 切到 B 控制器时,B 使用了 A 的 delegate
将值进行了更改,那当我们回到 A 时,会发现那个值已经改变。
iOS 中的 protocol
一个 protocol 会定义一套接口,接口有两种:
- @required: 必须实现的方法
- @optional: 可选的实现方法
我们常常会接触到的 tableViewDataSource 里就有 protocol ,他在里面定义了一些方法让你去实现。
我们可以看到我们用 tableView 的时候必须实现的
1 2 3 4 5
| - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
|
都是在@required
里的,如果我们不实现他,那 tableView 就会空无一值。
而
1 2 3 4 5 6 7 8 9 10
| - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
……
|
等等是在@optional
里的,我们是可以选择不去实现他们的。
delegate
我们继续用tableView
举例,我们使用tableView
的时候,相当于调用了UITableView
这个类,让他来帮助我们生成一个 View。
但是这个 tableView 并不知道我们需要多高多宽,什么样子的 View,于是他需要我们进行传值。我们用来把值传给它的类就是一个 delegate 。
当然,我们经常用 self 来在本控制器下控制 tableView 。
自定义 delegate
看过了系统的一些delegate
,其实我们也是可以实现代理的,而且使用代理会有许许多多的好处。
我们以一个实例来说明,这个例子的逻辑关系基本如下:
现在让我们来实现他吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
@class DelegateController; @protocol TestDelegate <NSObject>
@required
@optional
-(void)DelegateTest:(DelegateController *)vc;
@end
|
我们先在.h
文件中创造delegate
,并声明他的@required
和@optional
。
1 2 3 4 5 6 7
|
@interface DelegateController : UIViewController
@property (nonatomic, weak) id<TestDelegate> delegate;
@end
|
然后我们再声明一个delegate
,之后我们就可以在DelegateController
里使用delegate
的方法了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
- (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor blueColor]; }
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ if ([self.delegate respondsToSelector:@selector(DelegateTest:)]) { [self.delegate DelegateTest:self]; } }
|
当然,如果我们现在 run 的话,不会有任何的反应,因为delegate
里的方法还没有进行实现。
我们还得这样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; [self setupDelegateView];
}
-(void)DelegateTest:(DelegatetestVC *)vc{ vc.view.backgroundColor = [UIColor orangeColor]; NSLog(@"\n delegate Test Success!"); }
-(void)setupDelegateView{ DelegateController *vc = [[DelegatetestVC alloc]init]; vc.delegate = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self presentViewController:vc animated:YES completion:nil]; });
}
|
效果大概就是这样啦