ios 常见的几种逆向传值方式
在iOS开发中,常见的几种逆向传值方式,有代理(delegate)、通知(NSNotification),block等等,其实还有一种方法。
1、委托代理
delegate只能是一对一之间的。他只能是navigation的栈里面的相邻控制器传值, 不能跨控制器传值。比如:a到b,b到c.,而不能从c传到a.
@protocol PassValueDelegate<NSobject>
@optional
- (void)VCValuePass:(UIViewController*)VC;
@end
delegate 为什么用assign, 这还是一道面试题呢
@property(assign,nonatomic)id delegate;
if([self.delegaterespondsToSelector:@selector(VCValuePass:)]){
[self.delegateVCValuePass:self];
[self.navigationControllerpopViewControllerAnimated:YES];}
2、通知(NSNotifacation)
通知的用处就随意多了, 首先他是多对多传值的, 不过要先注册成为监听者,才能收到通知。简单、便捷。不用通知的时候,记得移除。
2.1.发出通知 // object通知发布者(是谁要发布通知)userInfo:一些额外的信息(通知发布者传递给通知接收者的信息内容)
NSDictionary* dic =@{ @"name":@"翠花", @"sex":@"女"};
NSString* address =@"深圳特区";[[NSNotificationCenterdefaultCenter]postNotificationName:@"ValuePass"object:addressuserInfo:dic];
2.2.注册监听对象 name通知的名称。如果为nil,那么无论通知的名称是什么,监听器都能收到这个通知; Object通知发布者。如果为anObject和aName都为nil,监听器都收到所有的通知
[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(receiveValue:)name:@"ValuePass"object:nil];
- (void)receiveValue:(NSNotification* )notifi{
NSLog(@"%@, %@",notifi.object, notifi.userInfo);}
在注册成为监听者的页面, 要注意移除通知
- (void)receiveValue:(NSNotification* )notifi{
NSLog(@"%@, %@",notifi.object, notifi.userInfo);}
写到这里的时候,我还是block使用的小白, 只会一些简单的block使用,那天自己block精通了,在详细讲一下。
3、block
我使用的block主要是作为property属性实现页面之间传值。
__block关键字的主要作用是:__block对象在block中是可以被修改、重新赋值的。__block对象在block中不会被block强引用一次,从而不会出现循环引用问题。
__block和__weak关键字的区别:
__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。__block对象可以在block中被重新赋值,__weak不可以。__unsafe_unretained修饰符可以被视为iOS SDK 4.3以前版本的__weak的替代品,不过不会被自动置空为nil。所以尽可能不要使用这个修饰符。
情景描绘:由a控制器调到b,首先在b的.h文件声明
@property(copy,nonatomic)void(^passValueBlock)(NSDictionary* dict);// 刚刚把copy写成assign,一直再报错
在b的.m里面,想传值的时候在方法里面写上
NSDictionary* dic =@{@"name":@"翠花",@"sex":@"女"};
if(self.passValueBlock)
self.passValueBlock(dic);
在a的.m文件里写:
__blockViewController* blockSelf =self;
TwoViewController* twoVC = [[TwoViewControlleralloc]init];
twoVC.passValueBlock= ^(NSDictionary* dict){
[blockSelfgetdic:dict];};
4、传值
最后一种传值方式,是在无意中发现的,但也能传值。之前一直做a到b,b到c,c到d等等之类的控制器跳转的项目, 然后从后面的某个控制器跳转到前面的某个控制器。解决办法就是找到需要跳转的控制器,在导航控制器栈中的位置,然后跳转,后来发现,如果在需要跳转的控制器的.h文件声明一个变量,在跳转之前赋值,是可以传过去的。
在d控制器的方法:
ViewController* a =self.navigationController.viewControllers[0];
a.name=@"翠花";
[self.navigationControllerpopToViewController:oneVCanimated:YES];
但是有时候,a控制器在栈里面的位置不一样,所以index不一定是固定某个值,另一种方法
ViewController* oneVC =nil;
for(UIViewController* VCinself.navigationController.viewControllers){
if([VCisKindOfClass:[ViewControllerclass]]){
oneVC =(ViewController*) VC;
oneVC.name=@"翠花";
[self.navigationControllerpopToViewController:oneVCanimated:YES];}
}
在a控制器验证一下:
- (void)setName:(NSString*)name{
_name= name;
NSLog(@"%@",name);}