iOS中的数据传递

(以A控制器 ->B控制器 ->C控制器 的页面传值为例)

  1. 顺传

顺传就是在A控制器跳转至B控制器时,获取到B控制器中需要赋值的属性,对该属性进行赋值,当控制器完成跳转后,就完成了值的传递。

注意:对于跨级控制器的跳转,如A控制器与C控制器之间还有一个B控制,要将A控制器的值传到C控制器,不能使用顺传,可以使用通知。

  1. 逆传

逆传就是把B控制器的值传给A控制器,主要的三种逆向传值的方式为代理、通知、block。

2.1 代理

2.1.1 在B控制器中添加代理协议

@protocol SecondViewControllerDelegate <NSObject

设置代理方法(设置可选或必选)、添加代理属性

-(void)changeThestatus:(UIButton*)btn;

@property(nonatomic,weak)id<SecondViewControllerDelegate> 

2.1.2 在B控制器中调用代理方法

   if ([self.delegate respondsToSelector:@selector(changeThestatus:)]) {

       [self.delegate changeThestatus:sender];

}

2.1.3 在A控制器中添加代理协议

@interface FirstViewController ()<SecondViewControllerDelegate>

2.1.4 在获取到B控制的代码块中设置代理对象

如要跳转到B控制器,则在跳转方法中,实例化B控制器后设置代理对象

SecondViewController *secVc = [self.storyboard instantiateViewControllerWithIdentifier:@"second"];

  1. delegate = self;

2.1.5 定义代理方法

-(void)changeThestatus:(UIButton*)btn{

   [self.showBtn setBackgroundColor:btn.backgroundColor];

   [self.showBtn setTitle:btn.titleLabel.text forState:UIControlStateNormal];

}

2.2通知

2.2.1 在B控制器中发送通知(在跳转控制器的方法中)

object参数为包含传递值的对象或值本身

[[NSNotificationCenter defaultCenter]postNotificationName:@"change" object:sender];

2.2.2 在A控制其中注册通知观察者

必须注意在注册观察者要保证观察者的注册先于通知发送,否则将收不到通知,本例中注册观察者放在A控制器跳转到B控制器的方法中,在A控制器跳转到B控制器后,B控制器往回跳转A控制器时观察者已经生成。

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(changeShow:) name:@"change" object:nil];

2.2.3 定义观察者的实现方法

-(void)changeShow:(NSNotification*)notification

   UIButton *btn = notification.object

   [self.showBtn setBackgroundColor:btn.backgroundColor]

   [self.showBtn setTitle:btn.titleLabel.text forState:UIControlStateNormal];

}

2.3 Block

2.3.1 在B控制器中声明一个Block属性

typedef void(^myBlock)(UIButton*btn);

@property(nonatomic,copy)myBlock Nblock;

2.3.2 在B控制器跳转A控制器的方法中回调Block,或者是将这个属性作为方法参数,在方法中回调这个Block

   if (self.Nblock) {

       self.Nblock(sender);

}

2.3.3 在A控制器实例化B控制器的代码后,通过B控制器获取到Block属性,对Block进行实现定义,在此书对A控制器中需要传值的对象进行赋值

SecondViewController *secVc = [self.storyboard instantiateViewControllerWithIdentifier:@"second"];

  1. Nblock = ^(UIButton* btn){

       [self.showBtn setBackgroundColor:btn.backgroundColor];

       [self.showBtn setTitle:btn.titleLabel.text forState:UIControlStateNormal];

};

三种逆向传值方式的比较:

第一就是代理,这也是很常用的方式,特点是一对一的形式,而且逻辑结构非常清晰,就是当前类中完成不了的事情,叫给另外一个类去完成,当然前提是外另外一个类中可以获取到当前类。如在tableviewcell中有一个btn按钮是需要刷新tableview 数据的,此时在cell中就可以将tableview设置为代理对象,在tableview中获取到cel,cell.delegate = tableView设置代理对象完成后,定以代理方法的实现就可以完成,

当然这里面有一些细节,包括协议定义时,要用到关键字@required,和@optional来明确代理是否必须实现某些方法,代理的类型需用id类型,并写明要遵守的协议;并在在调用代理方法的时候需要判断代理是否实现该方法。

第二就是通知,通知的优点很明显,他是一对多的形式,而且可以在任意对象之间传递,不需要二者有联系。通知需要的注意点就是注册的通知中心需要手动移除,不然除了性能的问题还会有其他的问题出现,比如说一个控制器消失了之后还有因为某些事件而发出通知,造成不想要的结果。但是一个程序中如果使用过多的通知后,会造成业务逻辑的可读性降低,理解起来没有代理那么清晰

第三就是block了,这是苹果后来才加入的,也是目前开发比较常用的一种方式,功能比较强大,。它的最大特点就是回调,回调的意思简单的理解就是,将方法的申明、调用与方法实现分开,将实现部分写在需要传值的控制器中。而且回调时可以传入参数, block本身可以封装一段代码,因此在定义实现时,可以在实现部分写入需要执行的代码。可以说block简化了代理方法,使用起来更灵活、简便。通常用作方法的参数,在方法中进行回调。

原文地址:https://www.cnblogs.com/devChang/p/5590103.html