传值

传值

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简化了代理方法,使用起来更灵活、简便。通常用作方法的参数,在方法中进行回调。

原文地址:https://www.cnblogs.com/Mrliheng/p/5438321.html