iOS开发中数据传递的方法有很多种,我这里整理一下常用的NSNotification、Block、Delegate和KVO四种方式,仅供参考,具体使用要看开发中的需求,以及项目业务逻辑的需要.希望在适当的场景和业务下选择合适的方式去提高开发效率.
Block:
block
是OC中一种对象和对象的通信方式,是一对一的关系.可以用于控制器与控制器的逆向传递数据。相比较代理而言的话,Block更加简洁灵活一点,不需要定义繁琐的协议方法,但通信事件比较多的话,建议使用Delegate;用block的话,一定要注意self的使用,防止循环引用导致的内存泄露.
用法:在a类中1,定义和2,回调block,在b类中3,实现block.
举例:
一, 按钮的触发事件.
1,定义block(有参数无返回值类型)
@property (nonatomic, copy) void(^didSelectDetailButton)(UIButton *sender);
2,block的回调.
- (void)pressDetailBtn:(UIButton *)sender{
if (self.didSelectDetailButton) {
self.didSelectDetailButton(sender);
}
}
3,block的具体实现.
cell.didSelectDetailButton = ^(UIButton *sender) {
SALookHaveSharedDetailController *haveVC = [SALookHaveSharedDetailController new];
haveVC.dataArray = detailArray.mutableCopy;
[weakSelf.navigationController pushViewController:haveVC animated:YES];
};
二,block从后向前传值
1、在第二个视图控制器的.h文件中定义声明Block属性(block的定义):
//定义block
@property (nonatomic,copy) void (^NextViewControllerBlock)(NSString *tfText);
2, .m(block 的回调)
- (IBAction)BtnAction:(id)sender {
//判断block是否为空
if (self.NextViewControllerBlock) {
self.NextViewControllerBlock(self.inputTF.text);
} [self.navigationController popViewControllerAnimated:YES];
}
3, 第一个控制器(block的实现)
- (IBAction)btnClicked:(id)sender {
NextViewController*nextVC =[[NextViewController alloc]init];
nextVC.NextViewControllerBlock= ^(NSString *tfText){ self.nextVCInfoLabel.text=tfText; }; [self.navigationController pushViewController:nextVC animated:YES];
}
代理:
delegate
是是一对一的关系,通过setDelegate来设置代理对象,最典型的例子是常用的TableView.用代理的话,可以接收到调用协议方法的返回值,它定义的方法要按照一定的规范来写,这样易读性非常好,利于后期项目的维护以及修改。相比较而言代码量比较大.
用法:
在a类中1,定义代理和2,回调,在b类中3,指定代理对象4,遵循协议5,实现代理方法.
举例:
1,定义代理
@property (nonatomic, weak) id<SAAddJobPointRuleCellDelegate> delegate;
@protocol SAAddJobPointRuleCellDelegate <NSObject>
- (void)tapAddJobPointRule:(SAAddJobPointRuleCell *)ruleCell;
@end
2,回调
- (void)tapAddAction:(UITapGestureRecognizer *)sender{
if ([self.delegate respondsToSelector:@selector(tapAddJobPointRule:)]) {
[self.delegate tapAddJobPointRule:self];
}
}
3,指定代理对象
self.cardSceneView.delegate = self;
4,遵循协议
@interface TestController ()<TestCardSceneViewDelegate>
5,实现代理方法
- (void)tapAddJobPointRule:(SAAddJobPointRuleCell *)ruleCell{
self.isSelectReset = NO;
SAGetAllShipperController *allVC = [SAGetAllShipperController new];
allVC.selectIndex = ruleCell.cellIndex;
[self.navigationController pushViewController:allVC animated:YES];
}
KVO:
KVO
( Key-Value Observing),是Foundation框架提供的一种机制,可以一对多.使用KVO,可以方便地对指定对象的某个属性进行观察,(一个对象能够观察另外一个对象的属性的值,并且能够发现值的变化。)被观察的属性对应的对象 来 添加 和 移除 观察者.只能用来对属性作出反应,而不会用来对方法或者动作作出反应只负责把通知发出去,至于其他的事情就不管了,因此他们没有返回值.注意:我们观察的属性必须使用strings来定义.
用法:
1.由被观察的对象调用方法, 添加观察者:addObserver:forKeyPath:options:context:
2.一旦被观察的属性发生改变, 系统会调用这个方法:observeValueForKeyPath:ofObject:change:context:方法
3.解除观察者身份:removeObserver:forKeyPath:context:
举例:
1,定义属性:
@interface ShipperModel : NSObject
@property (nonatomic, copy) NSString *togetherString;
@property (nonatomic, copy) NSString *separateString;
@end
2,添加观察者
[_shipperModel addObserver:self forKeyPath:@"togetherString" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];
[_shipperModel addObserver:self forKeyPath:@"separateString" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];
3,监测变化
#pragma mark -
#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
}
4,解除身份
- (void)dealloc {
[self.shipperModel removeObserver:self forKeyPath:@"togetherString"];
[self.shipperModel removeObserver:self forKeyPath:@"separateString"];
}
通知:
NSNotification
是苹果提供的一种消息机制, 观察者只要向消息中心注册, 即可接受其他对象发送来的消息,消息发送者和消息接受者两者可以互相一无所知,完全解耦。NSNotification可以应用于任意时间和任何对象,可以一对多.但只负责把通知发出去,至于其他的事情就不管了,因此他们没有返回值
用法:a类中创建和移除通知,以及响应通知所要做的操作.b类通知中心发送通知
1,注册一个观察者
2,给通知中心发送一个消息
3,清除观察者
举例:
1,通知中心添加观察者
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(fifthStepAction:) name:@“fifthStep” object:nil];
}
2,响应通知所要做的事件操作.
// object 和 userInfo可以带来想要接收的值
- (void)fifthStepAction:(NSNotification *)noti{
NSDictionary *dict = noti.userInfo;
self.isSettedSecondDismension = [dict[@"isSetted"] boolValue];
self.typeName = dict[@"typeName"];
}
//- (void)fifthStepAction:(NSNotification *)noti{
// self.isFromAddSureBack = [noti.object boolValue];
//}
3,移除通知
- (void)dealloc{
[[NSNotificationCenter defaultCenter]removeObserver:self];
}
4,通知中心发送通知
// object 和 userInfo可以带来想要接收的值
if (self.isTest) {
NSNotification *noti = [[NSNotification alloc]initWithName:@“fifthStep” object:nil userInfo:dict];
[[NSNotificationCenter defaultCenter] postNotification:noti];
[self.navigationController popToViewController:targetVC animated:YES];
}