查看: 1405|回复: 0

[IOS开发教程] iOS(闭包)block传值详解

发表于 2018-4-13 08:00:05

在iOSAPP开发的过程中 我们会用到很多需要传值的地方 传值的方式也多种多样 有:代理传值、通知传值、KVC、KVO、block、单例 等。其中block 因为其简洁实用规范的代码 无疑是大牛们传值的不二选择 但对于初学者来说要理解并能运用 起初确实有些难以理解 以下我将细细的介绍下block

首先我总结了一下block的公式:

  1. 步骤1.block 的声明 返回值类型(^block 的名字)(参数列表);
  2. 步骤2.block 实现 block的名字 = ^(参数列表)(){};
  3. 步骤3.block 的调用 block的名字();

下面是一个简单的block

  1. // 声明
  2. void(^blockName)(int num,NSString *string);
  3. // 实现
  4. blockName = ^(int num,NSString *string)
  5. {
  6. NSLog(@"%d,%@",num,string);
  7. };
  8. // 调用
  9. blockName(520,@"phyone_");
  10. }
复制代码

由该例可以看出block的代码执行顺序和其他的代码执行顺序不一样 它是先执行声明代码 然后执行调用代码 最后才执行实现代码 由此我们利用block的回调性质 达到我们传值效果 当然这只是在一个页面的一段代码 只是说明了它具有传值的作用 下面我们来试试 多页面之间的block反向传值 由于是反向传值 所以我们创建两个ViewController (ViewController,Next_ViewController)先由ViewController跳到Next_ViewController里将里面的值反向传给ViewController
以下是代码

ViewController.m里面

  1. - (void)viewDidLoad {
  2. [super viewDidLoad];
  3. self.view.backgroundColor = [UIColor purpleColor];
  4. UILabel *lable = [[UILabel alloc]initWithFrame:CGRectMake(100, 200, 200, 100)];
  5. lable.backgroundColor = [UIColor brownColor];
  6. [self.view addSubview:lable];
  7. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)];
  8. [self.view addGestureRecognizer:tap];
  9. }
  10. - (void)tap
  11. {
  12. Next_ViewController *NVC = [[Next_ViewController alloc]init];
  13. NVC.block = ^(NSString *content){
  14. NSLog(@"%@",content);
  15. UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(100, 200, 100, 100)];
  16. [button setTitle:content forState:UIControlStateNormal];
  17. button.backgroundColor = [UIColor orangeColor];
  18. [self.view addSubview:button];
  19. };
  20. [self presentViewController:NVC animated:YES completion:nil];
  21. }
复制代码

Next_ViewController.h里面

  1. //block 是分配在栈里面的用copy
  2. @property(nonatomic,copy) void(^block)(NSString *content);
复制代码

Next_ViewController.m里面

  1. <p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;">{</span></p>
  2. <p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;"> void(^imageNameBlock_1)(NSString *imageName);</span></p>
  3. <p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;"> void(^lableBlock)(NSString *tontentText);</span></p>
  4. <p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;">}</span></p>
复制代码
  1. - (void)viewDidLoad {
  2. [super viewDidLoad];
  3. self.view.backgroundColor = [UIColor orangeColor];
  4. UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
  5. button.frame = CGRectMake(100, 200, 100, 50);
  6. [button setTitle:@"123456" forState:UIControlStateNormal];
  7. button.backgroundColor = [UIColor redColor];
  8. [button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
  9. [self.view addSubview:button];
  10. }
  11. - (void)buttonAction:(UIButton *)sender
  12. {
  13. // 点击按钮 返回上一个页面 同时通过block 把这个值传到上一个页面
  14. self.block(sender.titleLabel.text);
  15. [self dismissViewControllerAnimated:nil completion:nil];
  16. }
复制代码

另外:block 还有两个问题

1.怎么改变block里面的值

用上面的代码 在ViewController.m viewDidLoad 里面 添加代码

  1. 1.局部变量
  2. 定义一个图片名字的Block
  3. */
  4. // 局部变量
  5. void(^imageNameBlock)(NSString *imageName);
  6. // 如果想修改Block里面的值 需添加__block修饰
  7. // __block UIImage *image;
  8. imageNameBlock = ^(NSString *imageName)
  9. {
  10. image = [UIImage imageNamed:imageName];
  11. self.view.backgroundColor = [UIColor colorWithPatternImage:image];
  12. };
  13. imageNameBlock(@"17.jpg");
复制代码

就会出现 Use of undeclared identifier 'image' 错误情况 原因是我们试图改变block里面的值 解决办法就是 添加 __block 修饰(解注释

__block UIImage *image;) 就行了

2.block的循环引用

用上面的代码 在ViewController.m viewDidLoad 里面 添加代码

  1. // 全局变量
  2. // block循环 引用 解决 我们用弱引用 __block
  3. __weak ViewController *VC = self;
  4. __block UIImage *image = nil;
  5. imageNameBlock_1 = ^(NSString *imageName)
  6. {
  7. image = [UIImage imageNamed:imageName];
  8. VC.view.backgroundColor = [UIColor colorWithPatternImage:image];
  9. };
  10. UILabel *lable = [[UILabel alloc]initWithFrame:CGRectMake(100, 200, 200, 100)];
  11. lable.backgroundColor = [UIColor brownColor];
  12. [self.view addSubview:lable];
  13. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)];
  14. [self.view addGestureRecognizer:tap];
复制代码

再添加两个方法

  1. - (void)loadData
  2. {
  3. imageNameBlock_1(@"17.jpg");
  4. }
  5. - (void)viewWillAppear:(BOOL)animated
  6. {
  7. [self loadData];
  8. }
复制代码

当出现循环引用是我们用__weak修饰下 但具体机制还不太懂 希望高人指点,感谢大家对程序员之家的支持。



回复

使用道具 举报