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

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

  1. OS笔记047代理传值和block传值

    在两个不同的控制器之间传递数据,可以使用代理传值或者block传值. 例子是一个简单通讯录. 主界面如下: 添加联系人界面 查看/编辑联系人界面:默认是查看模式,点击编辑后进入编辑模式 编辑模式 数据 ...

  2. 荼菜的iOS笔记--UIView的几个Block动画

    前言:我的第一篇文章荼菜的iOS笔记–Core Animation 核心动画算是比较详细讲了核心动画的用法,但是如你上篇看到的,有时我们只是想实现一些很小的动画,这时再用coreAnimation就会 ...

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

    一.属性传值 对于属性传值而言,相对于其它的三种 方法来说,是最基础,最简单的一种 方法,但,属性传值 有很大的局限性,因为是适用于第一个界面向第二个界面传 值,第二个向第三个界面传值等等.N界面向N ...

  4. iOS传值之block传值(一)

    ios4.0系统已开始支持block,在编程过程中,blocks被Obj-C看成是对象,它封装了一段代码,这段代码可以在任何时候执行.Blocks可以作为函数参数或者函数的返回值,而其本身又可以带输入 ...

  5. IOS传值之Block传值(二)

    @interface QWViewController : UIViewController @property(nonatomic,strong)UILabel *label; @property( ...

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

    ios 页面间传值有许多,前边已经分享过属性传值和代理传值,今天主要说一下单例传值和 block 传值 单例传值:单例模式一种常用的开发的模式,单例因为在整个程序中无论在何时初始化对象,获取到的都是同 ...

  7. iOS 再谈 代理传值,block反向传值

    本贴的例子是:有A和B两个界面,要实现的效果就是先让A跳转到B,然后B中有个颜色的参数,当B跳转到A时,把这个颜色的参数传递给A,在A中利用这个颜色改变自己界面的颜色. 第1步:在发送者(界面B)中, ...

  8. iOS开发之巧用Block和代理方法结合来传值

    好久没写技术博客了,因为996的工作周期已经持续好几个月了.每天晚上回家都没有太多精力学习很多其他的东西,而且很多时候是接着完善工作的项目的模块开发.所以博客停歇了这么久,更新率也低了不少,今天补充一 ...

  9. iOS开发——代理与block传值

    一.代理传值的方法 1.Hehe1ViewController.h中 #import <UIKit/UIKit.h> @protocol Hehe1ViewControllerDelega ...

随机推荐

  1. arcgis api for js 地图查询

      arcgis api for js入门开发系列四地图查询(含源代码) 上一篇实现了demo的地图工具栏,本篇新增地图查询功能,包括属性查询和空间查询两大块,截图如下: 属性查询效果图: 空间查询效 ...

  2. 数据库SQL优化大总结之 百万级数据库优化方案2

      网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后, ...

  3. python 学习之FAQ:find 与 find_all 使用

      FAQ记录   1. 错误源码 错误源码如下 def fillUnivList(_html,_ulist): soup =BeautifulSoup(_html,'html.parser') fo ...

  4. jsop解析获得htmldome

    package com.open1111.jsoup; import org.apache.http.HttpEntity;import org.apache.http.client.methods. ...

  5. HDU 2602 Bone Collector骨头收藏者(01背包)

    题意:收藏骨头. 思路: 常规的01背包. #include <iostream> #define N 1005 using namespace std; int volume[N]; / ...

  6. adc verilog spi 时序

    我用的是adc081sd芯片,(由于我们使用的是FPGA不用像单片机那样考虑极性cpol,相位cpha,下面仅仅介绍下跟单片机比较下) 什么是cpol:若cs被拉为低电平时sclk(时钟)是高那么cp ...

  7. JQuery笔录

    1.jQuery 的 hide() 函数,隐藏了 HTML 文档中所有的 <p> 元素.<script type="text/javascript">$(d ...

  8. 【洛谷1501】[国家集训队] Tree II(LCT维护懒惰标记)

    点此看题面 大致题意: 有一棵初始边权全为\(1\)的树,四种操作:将两点间路径边权都加上一个数,删一条边.加一条新边,将两点间路径边权都加上一个数,询问两点间路径权值和. 序列版 这道题有一个序列版 ...

  9. jquery iCheck 插件

    1 官网:http://www.bootcss.com/p/icheck/#download 2 博客:https://www.cnblogs.com/xcsn/p/6307610.html http ...

  10. 51nod——2478 小b接水(预处理 思维)

    我本来想把每个谷都处理了,想了下觉得不好办.后来看其他人写的是处理每个位置,把每个位置可以接的水累加起来.整挺好. #include <bits/stdc++.h> using names ...