iOS(闭包)block传值详解

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

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

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

下面是一个简单的block

//  声明
  void(^blockName)(int num,NSString *string);
//  实现
  blockName = ^(int num,NSString *string)
  {
    NSLog(@"%d,%@",num,string);
  };
//  调用
  blockName(520,@"phyone_");
} 

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

ViewController.m里面

- (void)viewDidLoad {
  [super viewDidLoad];
  self.view.backgroundColor = [UIColor purpleColor];
 UILabel *lable = [[UILabel alloc]initWithFrame:CGRectMake(100, 200, 200, 100)];
  lable.backgroundColor = [UIColor brownColor];
  [self.view addSubview:lable]; 

  UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)];
  [self.view addGestureRecognizer:tap];
}
- (void)tap
{
  Next_ViewController *NVC = [[Next_ViewController alloc]init];
  NVC.block = ^(NSString *content){
    NSLog(@"%@",content);
    UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(100, 200, 100, 100)];
    [button setTitle:content forState:UIControlStateNormal];
    button.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:button];
  };
  [self presentViewController:NVC animated:YES completion:nil];
}

Next_ViewController.h里面

//block 是分配在栈里面的用copy
@property(nonatomic,copy) void(^block)(NSString *content); 

Next_ViewController.m里面

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

另外:block 还有两个问题

1.怎么改变block里面的值

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

 1.局部变量
 定义一个图片名字的Block
 */
//  局部变量 

  void(^imageNameBlock)(NSString *imageName);
//  如果想修改Block里面的值 需添加__block修饰 

//  __block UIImage *image;
  imageNameBlock = ^(NSString *imageName)
  {
    image = [UIImage imageNamed:imageName];
    self.view.backgroundColor = [UIColor colorWithPatternImage:image];
  };
  imageNameBlock(@"17.jpg"); 

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

__block UIImage *image;) 就行了

2.block的循环引用

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

//  全局变量
//  block循环 引用 解决 我们用弱引用 __block
  __weak ViewController *VC = self; 

  __block UIImage *image = nil;
  imageNameBlock_1 = ^(NSString *imageName)
  {
    image = [UIImage imageNamed:imageName];
    VC.view.backgroundColor = [UIColor colorWithPatternImage:image];
  };
  UILabel *lable = [[UILabel alloc]initWithFrame:CGRectMake(100, 200, 200, 100)];
  lable.backgroundColor = [UIColor brownColor];
  [self.view addSubview:lable]; 

  UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)];
  [self.view addGestureRecognizer:tap]; 

再添加两个方法

- (void)loadData
{
  imageNameBlock_1(@"17.jpg");
} 

- (void)viewWillAppear:(BOOL)animated
{
  [self loadData];
} 

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

您可能感兴趣的文章:

  • iOS中详解Block作为property属性实现页面之间传值
  • 一篇文章让你看懂IOS中的block为何再也不需要WeakSelf弱引用
  • iOS中block变量捕获原理详析
  • iOS MRC 下 block 循环引用问题实例讲解
  • 浅谈iOS 对于block的一点理解
  • iOS在Block中修改外部变量值的实现代码
  • iOS面试中如何优雅回答Block导致循环引用的问题
  • IOS 使用Block二次封装AFNetworking 3.0详解
  • iOS通过逆向理解Block的内存模型
  • iOS利用Block逆向传值的方式详解
  • iOS通过block在两个页面间传值的方法
  • iOS中Block的回调使用和解析详解
  • iOS 9 更新之Safari广告拦截器(Content Blocker)开发教程
(0)

相关推荐

  • iOS通过逆向理解Block的内存模型

    前言 正常情况下,通过分析界面以及 class-dump 出来头文件就能对某个功能的实现猜个八九不离十.但是 Block 这种特殊的类型在头文件中是看不出它的声明的,一些有 Block 回调的方法名 dump 出来是类似这样的: - (void)FM_GetSubscribeList:(long long)arg1 pageSize:(long long)arg2 callBack:(CDUnknownBlockType)arg3; 因为这种回调看不到它的方法签名,我们无法知道这个 Block

  • iOS MRC 下 block 循环引用问题实例讲解

    下面一段代码给大家介绍iOS MRC 下 block 循环引用问题 //注意此__block会复制一份指针出来 一次原始的指针如果置为nil的话,此处复制出来的指针还是野指针 __block __typeof(self)weakSelf = self; //__weak __typeof(self)weakSelf = self; //__weak Person *weakSelf = self; void (^block)(void) = ^(void){ //NSLog(@"name --&

  • iOS在Block中修改外部变量值的实现代码

    一,代码. - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 第一种是可以修改 static 全局变量:第二种是可以修改用新关键字 __block 修饰的变量. __block int blockLocal = 100; static int staticLocal = 100; void (^aBlock)(

  • iOS中Block的回调使用和解析详解

    Block 回调实现 先跟着我实现最简单的 Block 回调传参的使用,如果你能举一反三,基本上可以满足了 OC 中的开发需求.已经实现的同学可以跳到下一节. 首先解释一下我们例子要实现什么功能(其实是烂大街又最形象的例子): 有两个视图控制器 A 和 B,现在点击 A 上的按钮跳转到视图 B ,并在 B 中的textfield 输入字符串,点击 B 中的跳转按钮跳转回 A ,并将之前输入的字符串 显示在 A 中的 label 上.也就是说 A 视图中需要回调 B 视图中的数据. 想不明白的同学

  • iOS 9 更新之Safari广告拦截器(Content Blocker)开发教程

    下面通过图文并茂的方式给大家分享下这方面的知识,具体内容如下. 相对于谷歌对广告拦截的禁止,苹果与之态度截然相反,继Mac版Safari加入广告拦截工具之后,即将到来的iOS9对Safari也引入了内容拦截插件-Content Blocker,并且开发者可以使用最新的Xcode7开发以及使用iOS 9模拟器进行调试,下面,笔者将用一个简单的实例进行讲解如何开发Content Blocker. 在使用Google搜索时,排行靠前面的几条永远都是广告项,比如搜索"iPhone6",得到的结

  • iOS利用Block逆向传值的方式详解

    前言 在iOS通过代理逆向传值的方式详解一文中,分析了如何利用代理模式来逆向传值,其实还有一些其他的方式,如通知.Block等,相比较代理,我个人认为反而要简单些,但是需要处理好细节问题,如Block循环引用.还是用前文的案例,本次使用Block来实现,Block的基本知识本文不再赘述. 一.书写规范 Block传值,需要注意的是,谁传值就需要定义Block,捕获方仅仅需要传递Block给传值方,并处理捕获的值. 传值方 1.定义Block用于传值 2.声明一个上述Block属性,这个属性的具体

  • iOS中详解Block作为property属性实现页面之间传值

    我们可以把Block当做Objective-C的匿名函数.Block允许开发者在两个对象之间将任意的语句当做数据进行传递,往往这要比引用定义在别处的函数直观.另外,block的实现具有封闭性(closure),而又能够很容易获取上下文的相关状态信息.定义Block变量,就相当于定义了一个函数.但是区别也很明显,因为函数肯定是在-viewDidLoad方法外面定义,而Block变量定义在了viewDidLoad方法内部.当然,我们也可以把Block定义在-viewDidLoad方法外部,例如上面的

  • iOS面试中如何优雅回答Block导致循环引用的问题

    前言 说到循环引用问题,最最最常遇到的,不是在项目中,而是在面试中.如果面试官问你开发中是否遇到过retain cycle,你如果说没遇到过,估计已经很难跟面试官继续友好的沟通下去了. 但是这个问题怎么回答呢,网络上千篇一律的答案-->使用Block的时候遇到过,使用__weakSelf 代替 self 等等,可以说这个答案没啥错,但是所有人都回答的一样,并不能突出我们的逼格,无法让面试官知道我们在这方面有过研究,有闪光点. 对于开发者来说,喜欢探索,喜欢挖掘不懂的知识,在面试官眼里会加分不少.

  • iOS中block变量捕获原理详析

    Block概述 Block它是C语言级别和运行时方面的一个特征.Block封装了一段代码逻辑,也用{}括起,和标准C语言中的函数/函数指针很相似,此外就是blokc能够对定义环境中的变量可以引用到.这一点和其它各种语言中所说的"闭包"是非常类似的概念.在iOS中,block有很多应用场景,比如对代码封装作为参数传递.这在使用dispatch并发(Operation中也有BlockOperation)和completion异步回调等处都广泛应用. Block是苹果官方特别推荐使用的数据类

  • 一篇文章让你看懂IOS中的block为何再也不需要WeakSelf弱引用

    前言: 最近都在折腾Sagit架框的内存释放的问题,所以对这一块有些心得. 对于新手,学到的文章都在教你用:typeof(self) __weak weakSelf = self. 对于老手,可能早习惯了到处了WeakSelf了. 这次,就来学学,如何不用WeakSelf. 1:从引用计数器开始: 这里先设计一个TableBlock类: @interface BlockTable : NSObject typedef void (^AddCellBlock)(); @property (nona

  • 浅谈iOS 对于block的一点理解

    block是对象,它封装了一段代码,这段代码可以在任何时候执行.block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值.它和传统的函数指针很类似,但是有区别:block是inline的,并且它对局部变量是只读的. Block的定义: int (^myBlock) (int a,int b) = ^(int a,int b){ return a+b; }; 定义了一个名为myBlock的blocks对象,它带有两个int参数,返回int.等式右边就是blocks的具体实现,是

  • iOS通过block在两个页面间传值的方法

    一.功能需求 在第一个页面中有一个button和一个label,label上默认显示"哈哈",点击button进入第二个页面.在第二个页面有一个UITextField和一个button2,点击button2回到第一个页面,但同时第一个页面的label上显示的文字修改为刚刚在UITextField写进去的文字. 二.先定义block 在要传值得那个页面定义含有block参数的方法,即在第二个页面的.h文件中定义: 重新定义:typedef void (^ReturnTextBlock)(

  • IOS 使用Block二次封装AFNetworking 3.0详解

    IOS 使用Block二次封装AFNetworking 3.0详解 现在我们网络请求大都用第三方工具-–AFNetworking: 其中,AFNetworking 3.0 是对 NSURLSession 进行的封装,简化了很多步骤,但是在现实开发中,我们可以将AFNetworking再次封装到一个类中,这样通过传去URL和Parameters 就可以进行网络请求. 具体实现步骤: 前期准备:导入AFNetworking第三方框架 1.新建一个工具类,继承自NSObject: 2.在.h 中宏定义

随机推荐