在两个不同的控制器之间传递数据,可以使用代理传值或者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

OS笔记047代理传值和block传值相关推荐

  1. block传值 链接

    iOS传值之block传值(一) 转载于:https://www.cnblogs.com/dqxu/p/4016117.html

  2. 四大传值详解:属性传值,单例传值,代理传值,block传值

    一:属性传值 传值情景:从前一个页面向后一个页面传值 a.在后一个页面,根据传值类型和个数,写属性 b.在前一个页面, 为属性赋值 c.在后一个页面, 使用值 例如: 第一个视图: #import & ...

  3. iOS UI 12 block传值

    // //  RootViewController.m //  UI- 12 block传值 // //  Created by dllo on 15/11/24. //  Copyright (c) ...

  4. 页面传值:属性,协议,Block传值

    1.属性传值和协议传值 1 #import "RootViewController.h" 2 #import "SecondViewController.h" ...

  5. ajax中post传值,ajax post传值

    一.字符串 $.ajax({ type: "POST", data: {"ID":id,"name":name}, url: "/ ...

  6. Android 组件系列-----Activity的传值和回传值

    在这篇随笔里将讲解Activity的传值和回传值. 一.通过startActivity来进行Activity的传值 在Android中,如果我们要通过一个Activity来启动另一个Activity, ...

  7. EntLib 3.1学习笔记(2) : Data Access Application Block

    EntLib 3.1学习笔记(2) : Data Access Application Block 简化实现通用数据访问功能的开发任务.应用程序可以在很多情况下使用应用程序块,例如读取显示数据.获得通 ...

  8. Android系列之Activity的传值和回传值

    Android系列之Activity的传值和回传值 Android 组件系列之Activity的传值和回传值 在这篇随笔里将讲解Activity的传值和回传值. 一.通过startActivity来进 ...

  9. 从底层本质上解析java是值传值还是引用传值

    关于java是值传值还是引用传值,在网上找了半天发现网上对于这个问题没有一个合理的解释,特地写了这篇文章,希望能给这个问题一个正确的解释 这个问题涉及语言层次的设计问题,所以我会列出从底向上的的所有结 ...

最新文章

  1. 人工神经网络秒变脉冲神经网络,新技术有望开启边缘AI计算新时代
  2. 20165303实验一 Java开发环境的熟悉
  3. 警惕!Cisco产品的假冒和水货
  4. STM32中STD、HAL、LL库比较
  5. 基于TextRank的关键词提取算法
  6. 夜神模拟器模拟安卓测试_使用模拟进行测试
  7. 前端学习(1257):基于promise处理ajax请求
  8. ModuleNotFoundError: No module named ‘torch.utils.serialization‘
  9. C#找出接口的所有实现类并遍历执行这些类的公共方法
  10. maven简单了解,没有Maven和使用Maven的区别
  11. SPSS26中文免费版下载和安装教程
  12. 微信公众号授权登录重复登录不跳转
  13. Excel中如何实现批量中文转拼音
  14. Js逆向:建筑市场监管平台
  15. win10黑屏Duilib资源加载失败
  16. contest11 CF510E div2 ooxxx oooox oooox
  17. 汉诺塔问题(Hanoi塔)
  18. WinKtv中文版介绍
  19. OsgEarth中设置模型运动路径,并绘制雷达扫描、动态实时绘制运动轨迹、跟随彩带
  20. win10计算机名访问win7,Win10和Win7共享打印机设置方法

热门文章

  1. Android对话框动态加载布局
  2. 20200210:(leetcode 623)在二叉树中增加一行
  3. 20191017:C++入门经典书籍学习目录01
  4. 高级工计算机操作试题及答案,计算机系统操作高级工试题和答案[1]
  5. oracle无效的关系运算符_每日一课 | Java 8中的instanceof运算符和访客模式替换
  6. 物联网核心安全系列——物联网安全需求
  7. NIPS 又!放!票!了!
  8. 微软总裁呼吁:AI刷脸,美国政府该管一管了
  9. 像人一样脑补世界!DeepMind历时一年半搞出GQN,登上Science
  10. 成都刘女士的第一场锤子科技发布会 | 现场特写