1. 属性传值(前面的界面给后面传值)

 第一步: 在 SecondViewController.h 文件里定义一个存放传过来值的变量 contents

 #import <UIKit/UIKit.h>

 @interface SecondViewController : UIViewController

 // 第一步:声明属性,用于存放传过来的值
@property (nonatomic, copy) NSString *contents; @end

 第二步: 在 FirstViewController 的按钮点击方法里给 SecondViewController 的 contents 属性赋值

 - (void)loginButtonClick:(UIButton *)sender
{
// 创建对象
SecondViewController *secondVC = [[SecondViewController alloc] init]; // 第二步:进行赋值
secondVC.contents = self.rootView.userTextField.text; // 导航控制器push栈中
[self.navigationController pushViewController:secondVC animated:YES];
}

 第三步: 在 SecondViewController 将传过来的值显示, 使用 contents 属性给 nameLabel 赋值(在 viewDidLoad 中)

// 第三步:显示内容
self.nameLabel.text = self.contents;

2. 协议传值(后面的界面给前面传值)

 第一步: 声明协议(在委托方(SecondViewController)的 .h 文件中声明)

 #import <UIKit/UIKit.h>

 #warning 第一步:在SecondViewController.h里声明协议
@protocol SecondViewControllerDelegate<NSObject> // 声明协议方法
- (void)passValueWithString:(NSString *)textString; @end @interface SecondViewController : UIViewController @end

 第二步: 声明代理人(在委托方(SecondViewController)的 .h 文件中声明代理人, 代理人是一个属性)

 @interface SecondViewController : UIViewController

 #warning 第二步:声明代理人

 // 代理的语义设置使用assign, 防止循环引用
@property (nonatomic, assign) id <SecondViewControllerDelegate> secondDelegate; @end

声明属性时的语义必须是 assign , 使用 retain , copy 会导致循环引用问题

 第三步: 执行协议方法(委托方(SecondViewController)在点击事件中使用代理属性调用代理的传值方法)

 // 实现点击事件方法(实现代理从后往前传值)
- (void)submitButtonClick:(UIButton *)sender
{
// 1.把输入的内容传到第一页 #warning 第三步:使用代理调用代理的传值方法
// [self.secondDelegate passValueWithString:self.eatTextField.text]; // 判断如果代理实现了方法进行调用(安全判断,当没有方法实现时不会导致程序崩溃)
if ([self.secondDelegate respondsToSelector:@selector(passValueWithString:)]) {
[self.secondDelegate passValueWithString:self.eatTextField.text];
} // 2.跳回到第一页
[self.navigationController popViewControllerAnimated:YES];
}

 第四步: 签订协议(代理人(FirstViewController)遵守协议)

 #warning 第四步:遵守代理协议
@interface FirstViewController ()<SecondViewControllerDelegate> @property (nonatomic, strong) UILabel *myLabel; @end

 第五步: 指定代理人(在代理人(FirstViewController) 跳转到委托方的点击事件方法中指定)

 // 代理人的点击事件方法(跳转到委托方)
- (void)rightBarClick:(UIBarButtonItem *)sender
{
// 1.创建视图控制器对象
SecondViewController *secondVC = [[SecondViewController alloc] init]; #warning 第五步:设置代理人
// 指定当前对象为代理人
secondVC.secondDelegate = self; // 2.push跳转
[self.navigationController pushViewController:secondVC animated:YES];
}

 第六步: 实现协议方法(代理人(FirstViewController)实现代理方法, 并接收传过来的值显示)

 #warning 第六步:实现代理方法,并接收传过来的值
- (void)passValueWithString:(NSString *)textString
{
// 将传过来的值显示
self.myLabel.text = textString;
}

3. Block传值

 1> 回顾Block

 2> Block注意事项

  在 controller 中定义 Block , 实现 Block 的时候, 如果 Block 里面需要使用当前控制器对象,不可以直接使用 self , 否则会引起循环引用

  解决办法:

   ① 使用 __block 修饰变量防止循环引用(MRC)

   ② 使用 __weak 修饰变量防止循环引用(ARC)

     // 使用__weak修饰防止循环引用
// __weak SecondViewController *secodVC = self; // 一般写法 // typeof(...) 得到括号中的类型
__weak typeof(self) secodVC = self; // 装逼写法 self.block = ^void () {
NSLog(@"这事block的实现"); secodVC.view.backgroundColor = [UIColor grayColor];
};

  typeof(...) 得到括号中的类型

 3> Block传值的两种方式

  方式一: 使用Block属性实现回调传值

  方式二: 在方法中定义Block实现回调传值

 4> Block属性传值

  第一步: 在传值方(SecondViewController)定义 Block 属性

 #import <UIKit/UIKit.h>

 @interface SecondViewController : UIViewController

 #warning 第一步:定义Block属性
@property (nonatomic, copy) void(^secondBlock)(NSString *); @end

  第二步: 在接值方(FirstViewController) 跳转到委托方的点击事件实现方法中 实现Block, 即Block回调

 // 跳转点击事件实现方法
- (void)barClick:(UIBarButtonItem *)sender
{
SecondViewController *secondVC = [[SecondViewController alloc] init]; #warning 第二步 实现Block
// Block回调
secondVC.secondBlock = ^void (NSString *string) {
// 得到Block回传的string,并赋值给myLabel
self.myLabel.text = string;
}; [self.navigationController pushViewController:secondVC animated:YES];
}

  第三步: 在传值方(SecondViewController)的返回点击事件中, 调用Block实现传值

 // 实现方法 进行Block传值
- (void)submitButtonClick:(UIButton *)sender
{
// 1.Block传值 #warning 第三步 Block传值, 调用Block
self.secondBlock(self.textField.text); // 2.返回第一页
[self.navigationController popViewControllerAnimated:YES];
}

 5> 在方法中定义Block传值

 6> Block存储域

  ① 没有使用局部变量的 Block 内存存储在全局区

  ② 使用局部变量的 Block 内存存储在 栈区

  ③ 当 Block 变量定义为属性的时候, 必须使用 copy 修饰, retain无效, 即 retain 和 assign 会造成野指针问题

  当对 Block 进行 copy 操作的时候, 此时 Block 的内存区域为 堆区

  当不使用 Block 时需要使用 Block_Release() 进行销毁

最新文章

  1. 萌新笔记——C++里创建 Trie字典树(中文词典)(一)(插入、遍历)
  2. python---基础之模块,列表,元组,字典
  3. button、label、textfield、页面跳转、传值
  4. C# 匿名函数 详解
  5. 【Alpha版本】冲刺-Day7
  6. hdu 1114 Piggy-Bank
  7. 多线程-NSOperation中使用ASIHttpRequest注意事项
  8. 关于RF 315MHz
  9. Java 和 Javascript 的 Date 与 .Net 的 DateTime 之间的相互转换
  10. Java-struts2 之中文乱码问题
  11. 写的一个Makefile
  12. Unity该插件NGUI学习(1)—— 环境结构
  13. 开源搜索引擎abelkhan
  14. CentOS(Linux)下安装dmidecode包
  15. vmware 14 密钥
  16. SQL Server 最大并行度
  17. 使用html5获取当前手机的经纬度,并接入百度地图API,查询出当前位置
  18. 11.match
  19. 将n的k位s置1
  20. node和yarn

热门文章

  1. ios Push证书 转换步骤
  2. REORG TABLESPACE on z/os
  3. AIX性能监控
  4. acpi参考网站
  5. Webstorm &amp; PhpStorm的序列号和证书
  6. Pyqt QTabWidget 简单的计算器集合
  7. sdut1598 周游列国【简单模拟题】
  8. Power BI for Office 365介绍
  9. 6-05使用SQL语句删除数据
  10. PHP计算程序运行时间的类