IOS笔记047-代理传值和block传值

在两个不同的控制器之间传递数据,可以使用代理传值或者block传值。

例子是一个简单通讯录。

主界面如下:

添加联系人界面

查看/编辑联系人界面:默认是查看模式,点击编辑后进入编辑模式

编辑模式

数据更新成功。

其中添加联系人界面的数据传递使用代理方式实现。

编辑联系人界面的数据传递使用block实现。

下面来看具体过程

1、整个界面搭建

在storyboard里拖拽四个控制器,其中联系人界面是一个UITableView。界面之间的跳转使用代码实现,但是要给每一个控制器指定一个标识。按功能分别指定为login,contact,add,edit.

? ?

具体细节我就不说了,关键是代理传值的实现。

2、代理传值

数据传递方向是从add控制器传递到contact控制器。至于为什么使用代理,主要是为了降低类之间的耦合度。

? ? 1、这里需要给add控制器添加一个代理对象,然后定义一个代理需要遵守的协议。

? ? // 代理实现逆传数据

? ? @classSLQContact; // 模型对象

? ? @classSLQAddViewController; //

? ? @protocol SLQAddViewControllerDelegate<NSObject>

?

? ? @optional

? ? // 代理方法

? ? - (void)addViewController:(SLQAddViewController *)addVC DidClickBtnWithContact:(SLQContact *)contact;

?

? ? @end

? ? @interface SLQAddViewController : UIViewController

? ? /*代理对象*/

? ? @property (strong, nonatomic) id<SLQAddViewControllerDelegate> delegate;

?

? ? @end

? ? 2、等需要传递数据时只需通知代理一声即可,不需要关心代理如何做。

在添加联系人界面里点击添加按钮后就去通知代理传递数据。

? ??// 添加联系人按钮,单击后传递数据到联系人控制器,并返回上一个界面

? ? - (IBAction)addBtn:(id)sender {

?? ? ? ?

? ? ? ? //传递模型数据

? ? ? ? SLQContact *temp = [SLQContactcontactWithName:_nameField.textandPhone:_phoneField.text];

?

? ? ? ? // 通知代理

? ? ? ? if([_delegate respondsToSelector:@selector(addViewController:DidClickBtnWithContact:)])

? ? ? ? {

? ? ? ? ? ? [_delegateaddViewController:selfDidClickBtnWithContact:temp];

? ? ? ? }

? ? ? ? // 返回上一个界面

? ? ? ? [self.navigationControllerpopViewControllerAnimated:YES];

? ? }

? ? 3、还有最关键的一步,那就是指定代理对象是谁

? ? ? ? 这里指定代理对象的是contact控制器,因为,要把数据传递给它,所以它作为接收者也就是代理方。

? ??// 添加按钮,按下后进入添加联系人界面

? ? - (IBAction)addBtn:(id)sender {

? ? ? ? //

? ? //? ? [self performSegueWithIdentifier:@"contactToAdd" sender:nil];

? ? ? ? // 通过代码获取storyboard中得控制器

? ? ? ? UIStoryboard *story = [UIStoryboard storyboardWithName:@"Main" bundle:nil];

? ? ? ? // 获取main。storyboard中得控制器,以标识符区分

? ? ? ? SLQAddViewController* addVC = [story instantiateViewControllerWithIdentifier:@"add"];

? ? ? ? // 代理逆传数据

? ? ? ? //如果通过代码跳转的话,必须知道目的控制器,整个程序中也只有这个时候才知道下一个控制器是谁,所以在这里指定代理对象为contact控制器再好不过了

? ? ? ? addVC.delegate = self;

? ? ? ? // 跳转到添加联系人界面? ? [self.navigationController pushViewController:addVC animated:YES];

? ? }

? ? // 实现代理方法,记得让类遵守协议

? ? - (void)addViewController:(SLQAddViewController *)addVC DidClickBtnWithContact:(SLQContact *)contact

? ? {

? ? ? ? // 添加数据到数组

? ? ? ? [_contacts addObject:contact];

?? ? ? ?

? ? ? ? // 刷洗表格

? ? ? ? [self.tableView reloadData];

? ? }

2、block传值

? ? 1、在编辑控制器中对block进行生声明以及定义

? ??// blocl传值使用

? ? @classSLQContact;

? ? // 声明block别名,参数为要传递的数据。

? ? typedef void(^SLQEditViewControllerBolok)(SLQContact *);

?

? ??@interface SLQEditViewController : UIViewController

? ? /*模型*/

? ? @property (strong, nonatomic) SLQContact *contact;

? ? /*block 对象*/

? ? @property (strong, nonatomic) SLQEditViewControllerBolok block;

? ? @end

?

? ? 2、在点击保存按钮后进行数据传递

? ??// 保存按钮事件

? ? - (IBAction)save:(id)sender

? ? {

? ? ? ? // 传递模型数据

? ? ? ? SLQContact *contact = [SLQContactcontactWithName:_nameField.textandPhone:_phoneField.text];

? ? ? ? // block实现传值,先检查是否有数据,如果有传递模型数据

? ? ? ? if(_block)

? ? ? ? {

? ? ? ? ? ? _block(contact);

? ? ? ? }

? ? ? ? // 回到上个界面

? ? ? ? [self.navigationControllerpopViewControllerAnimated:YES];

? ? }

? ? 3、关键一点还是要在数据接收方也就是contact控制器中对block内容进行包装

? ? ? 因为要通过代码跳转,同样需要知道目的控制器,跳转的地方就是选中cell的时候。

? ??// 选中cell后进入编辑界面

? ? - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

? ? {

? ? ? ? // 获取编辑控制器

? ? ? ? UIStoryboard *story? = [UIStoryboard storyboardWithName:@"Main" bundle:nil];

? ? ? ? // 获取目的控制器

? ? ? ? SLQEditViewController *editVC = [story instantiateViewControllerWithIdentifier:@"edit"];

? ? ? ? // 传递模型数据到edit控制器(这是一种顺序传值)

? ? ? ? editVC.contact = self.contacts[indexPath.row];

? ? ? ? // 使用block包装之后要进行的操作

? ? ? ? editVC.block = ^(SLQContact *contact){

? ? ? ? ? ? // 修改数据

? ? ? ? ? ? [self.contacts replaceObjectAtIndex:indexPath.row withObject:contact];

? ? ? ? ? ? // 刷新表格

? ? ? ? ? ? [self.tableView reloadData];

? ? ? ? };

? ? ? ? // 跳转到编辑界面

? ? ? ? [self.navigationControllerpushViewController:editVC animated:YES];

? ? }

3、顺序传值

顺序传递数据比价简单,只需要接收方有一个属性对要传递的数据进行接收就行。

上面在进入编辑控制界面时就要对数据进行传递,要把在联系人界面的数据传递到编辑控制器界面,然后对其进行修改。

? ??//?选中cell后进入编辑界面

? ? - (void)tableView:(UITableView?*)tableView didSelectRowAtIndexPath:(NSIndexPath?*)indexPath

? ? {

? ? ? ??//?获取编辑控制器

? ? ? ??UIStoryboard?*story? = [UIStoryboard?storyboardWithName:@"Main"?bundle:nil];

? ? ? ??//?获取目的控制器

? ? ? ??SLQEditViewController?*editVC = [story?instantiateViewControllerWithIdentifier:@"edit"];

? ? ? ??//?传递模型数据到edit控制器(这是一种顺序传值)

? ? ? ? editVC.contact?=?self.contacts[indexPath.row];

? ? ? ??//?使用block包装之后要进行的操作

? ? ? ? editVC.block?= ^(SLQContact?*contact){

? ? ? ? ? ??//?修改数据

? ? ? ? ? ? [self.contacts?replaceObjectAtIndex:indexPath.row?withObject:contact];

? ? ? ? ? ??//?刷新表格

? ? ? ? ? ? [self.tableView?reloadData];

? ? ? ? };

? ? ? ??//?跳转到编辑界面

? ? ? ? [self.navigationControllerpushViewController:editVC?animated:YES];

? ? }

上面的代码这样写。是因为在编辑控制器中已经定义了一个模型对象接收传递的数据。

? ??@interface SLQEditViewController : UIViewController

? ? /*模型对象,接收传递过来的数据*/

? ? @property (strong, nonatomic) SLQContact *contact;

? ? /*block 对象*/

? ? @property (strong, nonatomic) SLQEditViewControllerBolok block;

? ? @end

同样传递的地方也是在控制器跳转之前进行数据的传递。

4、总结

传值的方是由到导航控制器的行走方向决定的。

顺序传值:

? ? ? 由源控制器传递当目的控制器。

? ? ? 接收方有一个属性接收传递数据,在控制器跳转之前进行传递

逆序传值:

? ? ? 由源控制器传递当目的控制器。

? ? ? 代理:

? ? ? ? ? ? ? 在发送方对声明代理对象,然后定义代理协议,要传递的数据要放在代理方法的参数中,最后在触发事件后通知代理

? ? ? ? ? ? ? 在接收方设置代理位接收方,实现代理方法

? ? ? block:

? ? ? ? ? ? ? 在发送方对声明block,要传递的数据要放在block的参数中,最后在触发事件后调用block

? ? ? ? ? ? ? 在接收方设置block的内容

?

什么时候使用block?

? ? ? ? 逆传:用block来传值,处理网络的时候经常使用block封装代码。

? ? ? ? 请求网络数据(延迟) 先把展示到控件的代码先保存到block,等请求到数据的时候直接调用Block

?

?

?

时间: 2025-01-04 03:37:39

IOS笔记047-代理传值和block传值的相关文章

IOS传值--代理传值,block传值,NSNotificationCenter传值

一:利用代理传值,就是利用代理进行通信. 接口文件: #import <Foundation/Foundation.h> @protocol Cdelegate <NSObject> -(void)change:(NSString *)name; @end .h文件 @interface ViewController : UIViewController<Cdelegate> .m文件 - (IBAction)pushBB:(id)sender { BViewContr

属性传值,协议传值,block传值,单例传值四种界面传值方式

一.属性传值 对于属性传值而言,相对于其它的三种 方法来说,是最基础,最简单的一种 方法,但,属性传值 有很大的局限性,因为是适用于第一个界面向第二个界面传 值,第二个向第三个界面传值等等.N界面向N + 1界面传值.而在此基础上,必须知道跳转界面的明确位置及所要传的值的具体类型.在第二个界面中声明所要传值 类型的属性. @interface SecondViewController : UIViewController //声明一个字符串属性来保存第一个界面传过来的字符串内容 @propert

iOS页面传值之Block传值

场景A控制器中有一个Label  B控制器中有一个文本输入框textField A push 到B 当,B返回A时,我们让B中文本框的内容展示到A中去 第一步: 在B中定义Block #import <UIKit/UIKit.h> typedef void(^PassValueOption)(NSString*); @interface ZPViewControllerB : UIViewController @property(nonatomic,copy)PassValueOption o

iOS 页面间传值 之 单例传值 , block 传值

ios 页面间传值有许多,前边已经分享过属性传值和代理传值,今天主要说一下单例传值和 block 传值 单例传值:单例模式一种常用的开发的模式,单例因为在整个程序中无论在何时初始化对象,获取到的都是同一个对象,对象的属性相同,所以可以用来传值. block 传值 与 代理传值相似,主要用于第二个页面向第一个页面传值,block 传值具体步骤: 在第二个页面: 1.声明: block typedef void(^SendMessagerBlock) (NSString *str); 2.创建方法:

iOS开发——UI篇&amp;代理/通知/Block传值(实现UItableView分组的收缩与展开)

代理/通知/Block传值实现UItableView分组的收缩与展开 初始化之后出现下面的界面 准备: 1:定义一个BOOL值用来记录点击 1 @property (nonatomic, assign, getter = isOpen) BOOL open; 2:在相应的点击方法里面是实现点击 1 self.group.open = !self.group.open; 3:在numberOfRowsInSection中返回的时候使用三木判断是否点击,并且实现伸缩与展开, 1 return mod

iOS开发——代理与block传值

一.代理传值的方法 1.Hehe1ViewController.h中 #import <UIKit/UIKit.h> @protocol Hehe1ViewControllerDelegate <NSObject> - (void)backValueWith:(NSString*)str; @end @interface Hehe1ViewController : UIViewController @property(nonatomic,weak) id delegate; @en

ios block传值

iOS开发中的页面传值方式有很多种,最常见的是代理和属性传值方法,不过,block也可以传值,而且在一些特定的场合中,block传值会更简单,下面是一个我写的一个demo,大家可以参考一下. 在#import "AppDelegate.h"中,代码如下: 在第一个控制器中代码如下: 在第二个控制器的.h文件中代码如下: 在第二个控制器的.m文件中代码如下 以上就完成相应的两个界面之间的传值 版权声明:本文为博主原创文章,未经博主允许不得转载.

iOS block传值方法

iOS开发中的页面传值方式有很多种,最常见的是代理和属性传值方法,不过,block也可以传值,而且在一些特定的场合中,block传值会更简单,下面是一个我写的一个demo,大家可以参考一下. 在#import "AppDelegate.h"中,代码如下: 在第一个控制器中代码如下 在第二个控制器的.h文件中代码如下 在第二个控制器的.m文件中代码如下

代理&amp;Block 传值

刚学习苹果开发的时候不懂代理,Block,感觉好麻烦,就知道大概意思,现在回头看,发现就懂了,留一份自己的Demo希望初学的人能够看出点什么. 代理传值:在第二个界面输入值传给第一个界面 MainViewController #import <UIKit/UIKit.h> @interface MainViewController : UIViewController @property (nonatomic, retain) UITextField *labelTwo; @end #impo