前言
iOS常见的五种传值分别为属性传值,通知传值,代理传值,block传值,单例传值
属性传值
用于正向传值,简单,但对象之间得相关联
模拟一个场景, A->B(A传值B)
B.h文件定义一个变量
@interface lastViewController : UIViewController
@property(nonatomic,strong)NSString * str;
@end
A.m文件跳转并传值
lastViewController * last = [[lastViewController alloc]init];
// [[NSNotificationCenter defaultCenter]postNotificationName:nsnotificationName object:nil];
last.str = self.textField.text;
[self.navigationController pushViewController:last animated:YES];
}
通知传值
不需要编写多少代码,实现比较简单,对象可以不关联,跨层传值,一对多(发送一个通知,订阅该通知的都会得到相应,是同步的),通知使用过多显得太乱,不好调试
模拟一个场景 : C->B && C->A
订阅通知,尽量在delloc里移除该通知,注册通知和移除通知是成双成对(iOS8之前),这里附上两个链接
iOS尽量不要在viewWillDisappear:方法中移除通知
iOS 9 NSNotificationCenter移除问题
A订阅通知
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(value:) name:nsnotificationName object:nil];
}
A销毁移除通知
-(void)dealloc{
[[NSNotificationCenter defaultCenter]removeObserver:self];
}
或者移除单个通知
-(void)dealloc{
[[NSNotificationCenter defaultCenter]removeObserver:self name:nsnotificationName object:nil];
}
B和A控制器一样,最后在C发送通知
NSDictionary * dict = @{@"key":self.textField.text};
[[NSNotificationCenter defaultCenter]postNotificationName:nsnotificationName object:nil userInfo:dict];
记得先订阅,在发送再能接收到通知的
代理传值
代理传值一对一,可以定义多个方法,但定义代码太过繁琐
逆向传值 B->A
B.h : 声明协议,定义代理执行的方法,并定义一个该协议的属性
@protocol lastViewControllerDelegate<NSObject>
//方法可实现的
@optional
//方法必须实现
//@required
-(void)pushViewcontroler:(NSString *)str;
@end
@interface lastViewController : UIViewController
@property(nonatomic,weak)id<lastViewControllerDelegate>delagate;
@end
B.m
//设置视图将要消失时.通过代理传值
//判断代理是否存在,并且设置代理能够响应代理方法时,才执行代理方法
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
if (self.delagate && [self.delagate respondsToSelector:@selector(pushViewcontroler:)]) {
[self.delagate pushViewcontroler:@"哈哈"];
}
}
A.m 服从协议,设置代理,并实现协议的方法
//服从协议
@interface ViewController ()<lastViewControllerDelegate>
@end
- (IBAction)push:(id)sender {
lastViewController * last = [[lastViewController alloc]init];
//设置代理
last.delagate = self;
[self.navigationController pushViewController:last animated:YES];
}
//实现协议方法
-(void)pushViewcontroler:(NSString *)str{
self.textField.text = str;
}
block传值
代码简洁,反向传值,模拟场景 B->A
B.h声明block属性
@property(nonatomic,strong)void(^Myblcok)(NSString * str);
B.m调用该block
self.Myblcok([self.showLabel.text substringToIndex:<#(NSUInteger)#>]);
A.m 接收该block
lastViewController * last = [[lastViewController alloc]init];
last.Myblcok = ^(NSString *str) {
self.textField.text = str;
};
last.str = self.textField.text;
[self.navigationController pushViewController:last animated:YES];
block简单定义使用可以看看这篇 : iOS之轻松上手block(上)
单例传值
- 创建一个单例
@interface model : NSObject
@property(nonatomic,strong)NSString * str;
//暴露一个方法,供外界访问
+(model *)del;
@end
static model * del = nil;
@implementation model
+(instancetype)allocWithZone:(struct _NSZone *)zone{
return [model del];
}
+(model *)del{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
del = [[super allocWithZone:nil]init];
});
return del;
}
//在通过拷贝的时候创建对象时,会调用到-(id)copyWithZone:(NSZone *)zone,-(id)mutableCopyWithZone:(NSZone *)zone方法。因此,可以重写这些方法,让创建的对象唯一。
+ (id)copyWithZone:(struct _NSZone *)zone{
return [model del];
}
+ (id)mutableCopyWithZone:(struct _NSZone *)zone{
return [model del];
}
@end
2.A中为单例的属性赋值
- (void)viewDidLoad {
[super viewDidLoad];
model * del = [model del];
del.str = @"我是单例的属性";
}
3.B中获取单例属性
- (void)viewDidLoad {
[super viewDidLoad];
model * del = [model del];
self.showLabel.text = del.str;
}
了解单例的创建可以看看 :iOS中的单例模式
感言
这次是我对iOS最开始学习的内容回顾,自己的理解,有不对的望指出,谢谢
网友评论