传值
1 顺向传值
顺传 属性传值 运行方式为 A à B
原理: 在B页面的控制器中,创建需要的属性,由于控制器是由 A 跳到 B 的,因此可以在 A 中拿到 B 中的属性,直接赋值.(赋值在控制器跳转的时候完成)
- 在 B 中定义一个属性
- 在 A 中拿到 B 的非私有属性
- 在 A 中直接对 A 拿到的 B 的属性赋值即可.
方法: - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;
当我们拿到了segue也就拿到了他的属性,就可以拿到目标控制器这个属性,这时候也就相当于我们在A控制器里就拿到了B,也就可以给B设置数据了,这也就是所谓的顺传,主要是用到了这个方法。
2 逆向传值
逆传 包含三种方式 通知 代理 block(闭包)
>>> 通知:
1 什么是通知?
通知是一种消息传递方式,可以传递消息信息.
2 通知的特点?
- 通知必须包含:通知发布者,通知中心和通知的接受者.
- 通知的发布者包含:通知的名称,通知的发布者以及通知要传递的信息.
- 通知中心只是用来转发通知发布者发布的信息.
- 通知接收者又称为监听者:用来接收通知发送者发送的信息.
- 通知可以实现消息的一对多,一对一,多对一的传递方式.
- 通知可以实现越级传递,即通知消息的传递可以不受控制器层级数的限制传递信息.
3 通知使用注意事项:
- 通知使用的时候必须要先注册通知监听者,再发布通知,否则将接收不到通知发布的信息
- 通知使用完毕之后一定要在监听者对象释放前移除通知.
4 通知的使用步骤:
1> 在要发布通知的地方 注册并发布通知
[[NSNotificationCenter defaultCenter] postNotificationName:通知名 object:nil(通知的发布者) userInfo:通知信息];
2> 在需要接收信息的地方注册通知监听者接收通知
[[NSNotificationCenter defaultCenter] addObserver:self(通知观察者) selector:@selector(通知实现方法) name:@"通知名称" object:nil(通知的发布者)];
实现通知的方法.该方法实现要实现的操作
3> 移除通知监听者
[[NSNotificationCenter defaultCenter]removeObserver:self];
>>> 代理:
1 什么是代理?
当 B 想做一件事但是 B 做不了或者 B 想把做的事情通知给 A或者 A 想监听 B的时候.
原理: B 要对 A 进行传值(但是是 A 加载的 B),所以 B 要拥有已经创建的 B,所以 B 要有代理属性指向 A,所以要在 B 中设置代理协议.
2 代理使用的注意事项?
- 代理使用的时候只能从一个控制器传递到上一个控制器,不能隔控制器传递
- 代理是一对一是使用
3 代理的使用步骤
1> 在 B.h 中
遵守协议
@protocol Vc2Delegate
设置代理方法
@optional
- (void)passValue:(NSString *)value;
@property(nonatomic,assign)id<Vc2Delegate>delegate;
2> 在 B.m 中
实现在 B.h 中声明的方法
3> 在 A.m 中
设置自己为代理
遵守代理的协议
实现协议的方法
>>> block(闭包)
1> 什么是 block?
Block 是一中数据类型.一个代码块.其存在的标记是 ^ 符号
原理:因为 B 要对 A 传值,所以要在 B调用 block 的时候把值传给 A.
2> Block 的一般形式
返回类型(^block名)(形参类型)=^(形参列表){代码实现}
int(^sumBlock)(int,int) = ^(intX,intY){return X + Y}
使用的时候: block 名(实际参数)
一般使用 typedef 返回值类型 (^block名)(形参类型)
3> Block 使用特点
- 在 block 外部定义的变量在 block 内部是不能修改的,要想修改的时候,需要在外部定义的时候加上 __block
- 定义 block 的时候要使用 weak 修饰,避免产生循环使用.
- 在 block 内部应慎重使用 self.
4> 几种 block 的区别
> stack block:当 block 被定义的时候会被分配到 stack(堆)中的一块内存中.其特点是该 block 只能自己所声明的区域中有效.该区的代码块运行结束的时候该代码块就被销毁
> heap block:为解决上述问题,将block 代码由 stack copy 到 heap 区域(在 block 代码右侧代码块后面加上 copy).在 stack中的 block 代码块,系统会在调用它之后自动清理它,而在 heap 中的 block,与其他变量类似,接受计数器的管理,只有当计数器为0的时候才被销毁.
5> Block 的使用步骤
- 定义 block
- 在需要的地方调用并传入实参
3 通知/代理/ block 三者之间的对比
3.1 通知
1> 特点: 可以”一对多”,”一对一”,”多对多”的传值.
2> 使用步骤
> 发送通知
> 创建监听者
> 接收通知
> 移除监听者
3> 使用场景
> 多个控制器需要使用一个事件(通过通知的唯一通知名)
> 相隔多层的两个控制器之间的跳转.
4> 使用注意
> 在使用完将停止之后,一定要移除
> 通知接收的对象不好控制,因为只要调用一下该通知,并且通知名正确,就可以接收到该通知.
3.2 代理
> 特点:“一对一”,对于同一个协议,一个对象只能设置一个代理.所以单例对象不能使用代理.
> 代理更注重信息传递的过程,比如:信息什么时候开始,什么时候传输完成,数据传输的成功或者失败.
> 代理的使用一般比较多,比较大的公司(百度等)常用代理实现.
3.3 block
> 特点:block 是一个代码块,它以闭包的形式将内容传递,基本上可以传递任何内容.block 是一个注重结果的传输(比如传输的成功/失败)
> 闭包:能过读取其他函数内部变量的函数.就是在一段请求连续代码中可以看到调用参数和响应结果.因此使用 block 可以提高代码的可读性,扩展性和封装性.
> block 的循环引用问题
ARC 下: __weak typeof(self) weakSelf = self;
MRC 下: __block typeof(self) weakSelf = self;
> 它的最大特点就是回调,回调的意思简单的理解就是,将方法的声明、调用与方法实现分开,将实现部分写在需要传值的控制器中(即声明和调用在 B 中, 实现在 A中)。而且回调时可以传入参数, block本身可以封装一段代码,因此在定义实现时,可以在实现部分写入需要执行的代码。可以说block简化了代理方法,使用起来更灵活、简便。通常用作方法的参数,在方法中进行回调。