五种传值方式
本周主要学习了kvo传值,Block传值和通知传值三种传值方式,算上之前学的属性传值和协议传值共五种传值方式
属性传值
从前向后的传值方式,在A类中直接对B类的属性传值。
在A类中:
BViewController* bViewController = [[BViewController alloc] init];
bViewController.str = str;
协议传值
从后向前的传值方式。在B类中定义传值协议设置该协议的代理,并使A类遵守该协议,将A类赋值给B类的协议代理,使用代理调用A类的传值方法。
在B类设置协议:
@protocol RegisterViewControllerDelegate <NSObject>
-(void)pushString:(NSString*)str;
@end
声明该协议的代理:
@property id<RegisterViewControllerDelegate> delegate;
在A类实现协议方法
// 在A类实现方法
- (void) pushString:(NSString *)accontText {
_str = accontText;
}
设置代理B类的代理为A类
BViewController* bViewController = [[BViewController alloc] init];
// 全屏替换A界面
bViewController.modalPresentationStyle = UIModalPresentationFullScreen;
// 设置代理
enrollViewController.delegate = self;
[self presentViewController:enrollViewController animated:YES completion:nil];
在B类中调用方法传值
[self.delegate pushAccontText:str];
[self dismissViewControllerAnimated:YES completion:nil];
KVO传值
从后向前的传值方式。
KVO是苹果提供的一套事件通知机制。允许对象监听另一个对象的特定属性的改变,并在改变时接收到事件。由于KVO的实现机制,只针对属性才会发生作用,一般继承自NSObject的对象都默认支持KVO
KVO的使用条件
1. KVO:观察某一对象的某一个值的变化
2. 接收某个属性的字典观察通知,必要条件:(1)接收者必须知道发送者的存在
(2)接受者必须知道发送者的生命周期
KVO的使用方法
- 注册观测者
- (void) addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
1. observer: 观察者,监听属性变化的对象
2. keyPath: 要观察的属性名称,要和属性声明的名称一致
3. options: 对KVO机制进行配置,修改KVO通知的时机和内容
4. contest: 想要携带的其他信息,不过只能是同一视图的内容
四个options
// 返回改变后的新值
NSKeyValueObservingOptionNew = 0x01;
// 返回改变前的旧值
NSKeyValueObservingOptionOld = 0x02;
// 注册的时候就会发一次通知,改变后也会发通知
NSKeyValueObservingOptionInitial = 0x04;
// 改变之前发一次通知,改变之后发一次通知
NSKeyValueObservingOptionPrior = 0x08;
- 接受通知
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
1. keyPath: 观察的属性
2. object: 观察的对象
3. change: 这是一个字典类型的变量,通过键值对显示新的属性值和久的属性值
4. context: 注册时携带的信息
- 取消注册
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath
1. observer: 观察者
2. keyPath: 观察的属性
Block传值
从后向前的传值方式。
Block简介
Block就是一段匿名的代码块,是具有某种功能的代码块。
Block的使用方法
- 在B类自定义Block
// 自定义Block
typedef void(^UserAccontBlock)(NSMutableSet* userAccont);
- 声明一个block属性
// Block声明
@property (nonatomic, copy) UserAccontBlock userAccontBlock;
- 声明并实现Block的方法,对Block属性进行赋值
// .h文件中声明方法
- (void) sendUserAccontToLoginView:(UserAccontBlock)block;
// .m文件中实现方法
- (void) sendUserAccontToLoginView:(UserAccontBlock)block {
self.userAccontBlock = block;
}
- 判断Block是否存在,并给Block传递参数,即要传递的值
if (self.userAccontBlock != nil) {
self.userAccontBlock(self.userEnrollAccont);
}
- 在要接受传值的控制器中创建控制器对象,调用Block属性接收传值。
[enrollViewController sendUserAccontToLoginView:^(NSMutableSet* userAccont) {
self.userAccont = userAccont;
}];
通知传值
一般也是从后向前传值,可以跨越多个页面传值。
- 在发送者中实现一个方法进行发送通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"TransData" object:nil userInfo:_userAccont];
1. postNotificationName: 之后的参数就是这个通知的名字,要和接收者中的名字一样。
2. object: 接收对象
3. userInfo: 携带的参数,为字典类型的数据
- 在接收者中注册通知,建立“通知中心”
[[NSNotificationCenter defaultCenter] addObserver:self selector:@"receiveAccont" name:@"TransData" object:nil];
- 实现接收方法
- (void) receiveAccont:(NSNotification*)sender {
self.userAccont = sender.userInfo[@"content"];
}
- 在不使用的时候移除通知
- (void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"TransAccont" object:nil];
}