iOS-Block的使用

1、Block是什么?
 - 匿名函数
 - 截获自动变量
2、Block语法。
3、Block类型变量。
4、Block的用途。
 - 作为函数参数
 - 反向传值
 - 循环引用
(delegate差不多作用,但是显得更加简洁)


首先就是Block是什么?用一句话来概括就是带有自动变量的匿名函数。
那么我们解释清楚了什么是“匿名函数”,什么是“自动变量”,那么相信大家大概就对Block有了一个大概的认识。

  • 匿名函数
    匿名函数顾名思义就是不带名字的函数,在C语言中不允许这样的方法存在,而在OC中的Block则可以用指针来直接调用一个函数,但虽说如此我们还是需要知道指针的名称。(关于这点,额~~我们还是不要纠结的比较好。~!~~)
  • 自动变量
    自动变量在Block中的具体表现就是截获自动变量,来看下面这一段代码:
 int b = 0;
    void (^blo)() = ^{
        NSLog(@"Input:b=%d",b);
    };
    b = 3;
    blo();
    /**
     *    Input:b=0
     */

虽然我们在调用blo之前改变了b的值,但是输出的还是Block编译时候b的值,所以截获瞬间自动变量就是:在Block中会保存变量的值,而不会随变量的值的改变而改变。

我们再来看一段代码

int b = 0;
    void (^blo)() = ^{
        b = 3;
    };

这段代码编译出错,编译器提示的大概就是不能在Block中改变变量的值。因为在Block中截获了变量的瞬间值以后就不能再改变变量的值,如果想要在Block中改变变量的值,那么我们只需要在变量声明的时候加上__Block修饰符,像这样:

__block int b = 0;
    void (^blo)() = ^{
        b = 3;
    };

然而这样的情况又是允许的:

 NSMutableArray *array = [[NSMutableArray alloc]init];
    void (^blo)() = ^{
        [array addObject:@"Obj"];
    };

为什么呢,因为我们只是对截获的变量进行了操作,而没有进行赋值,所以对于截获变量,可以进行操作而不可以进行赋值。

还有一点需要注意,在Block中不可以对C语言数组进行操作,原因是:~~~不支持。。。。

结合匿名函数和截获自动变量的特性,Block可以做很多事情,我们下面在看。



我们来具体看一下Block语法的书写,我们首先来看一个完整的Block:

 ^ NSString *(NSString *a,NSString *b){
        return a;
    };

我们来分别解释下每一个部分都是什么东西:

  • “^”这个符号表示这是一个Block;
  • NSString *表示返回值。
  • (NSString a,NSString b)这个括号中是Block的参数,语法和C语言类似。

其实我们可以省略Block的返回值,像这样写:

^ (NSString *a,NSString *b){
        return a;
    };

这样写和上面那种写法是一模一样的,其实如果没有参数列表我们甚至可以省略参数列表,像这样:

^ {
        NSLog(@"我没有参数列表");
    };

如果把这段代码写完整,那么就是这样的:

^void(void) {
        NSLog(@"我没有参数列表");
    };


为什么需要Block变量?我们可以这样理解,我们通过这个Block变量来获取Block的指针,然后通过这个指针就可以来使用Block函数。我们先来看一下如何声明一个Block变量

      int (^Blo)(NSString *s1,NSString *s2);

对照前面的Block函数,我们可以比较容易的理解各个部分的含义:

他们分别是:

  • 返回值
  • 变量名
  • 参数列表

好的,然后我们用上面讲到的Block语法来对这个Block变量进行赋值:

    int (^Blo)(NSString *s1,NSString *s2);

    Blo = ^(NSString *s1,NSString *s2){
        return 1;
    };

然后我们就可以将这个Block变量当作C语言函数来使用了。



那么Block到底怎么用呢?

Block能够当作函数参数,首先我们声明一个Block类型变量 ,并加上typedef修饰符,像这样:

typedef void(^Blo)(NSString *s1,UIColor *c);

这样我们就可以使用Blo来表示这个Block,然后我就可以将Blo加入到函数参数中,我们来声明一个函数:

-(void)func:(Blo)BlockPra{

    BlockPra(@"Str",[UIColor redColor]);

}

然后我们可以这样使用这个函数:

[self func:^(NSString *s1, UIColor *c) {
        NSLog(@"%@",s1);
        self.view.backgroundColor = c;
    }];

是不是觉得十分眼熟,平时使用的许多回调当中大多都是这样的形式,可能其中其较多的就是网络回调了,我们只需要调用方法,然后在回调当中就可以对结果进行操作,很多苹果自己写的API都是使用了这样的方法,这样做的好处就是形式上十份简洁,当然像这种地方你使用delegate肯定也是可以的,但是表现上就没有Block那么简洁,使用起来也没有Block那么方便。

除此之外,Block还可以用来作为控制器之间的一个通信。
前面我们已经知道Blcok是一个匿名函数,同时也是一个指针,那么使用Block就可以弥补在iOS中函数传递的功能。通常是这么用的:

页面B的.h文件中定义了这样一个Block执政,然后声明了一个变量,像这样:

  typedef void(^Blo)(NSString *s1,UIColor *c);
  @property (nonatomic, copy) Blo block;

然后我们在页面A当中有这么一段代码:

ViewController *b = [[ViewController alloc]init];

    __weak  ViewController *wself = self;
    b.block = ^(NSString *s1,UIColor *c){
        NSLog(@"%@",s1);
        wself.view.backgroundColor = c;
    };
    [self.navigationController pushViewController:b animated:true];

然后在页面B的任意地方我们调用block变量,像这样:

     self.block(@"str",[UIColor redColor]);

都会在A页面中调用B页面传过来的参数,在A页面进行操作,对控制器A进行改变,这样的做法通常用做 控制器 反向传值。

在这里有一点需要注意就是Block的使用引起的循环引用。如果在Block中使用附有__strong修饰符的对象类型自动变量,那么当Block从栈复制到堆时,改对象为Block所有。这样容易引起循环引用,从而发生内存泄漏,然而我们只需要保证当前控制器也就是self在需要释放的时候正确释放就可以,所以我们再来看上面那段代码:

      __weak  ViewController *wself = self;

我们定义一个wself变量并加上__weak修饰符,在Block代码块中,所有需要self的地方都用wself来替代。这样就不会增加引用计数,所以Block持有self对象也就不会造成循环引用,从而造成内存泄漏。
不管是将Block当作函数参数,还是用来反向传值,其实都是对Block的本质,也就是“带有自动变量的匿名函数”的两个修饰,“带有自动变量”、“匿名函数”这两个特性 的应用。



总结一下Block到底是什么、用来干什么:

  • C++中的Struct(本文未提到)。
  • 用来弥补iOS中函数传递的功能。
  • 他是一段代码块的内存的指针。
  • 和delegate一样的功能,但是显的更加简洁。

作者:StrongX
链接:http://www.jianshu.com/p/ce238bd58d5b
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

时间: 2024-08-10 17:08:42

iOS-Block的使用的相关文章

iOS block从零开始

iOS block从零开始 在iOS4.0之后,block横空出世,它本身封装了一段代码并将这段代码当做变量,通过block()的方式进行回调. block的结构 先来一段简单的代码看看: void (^myBlock)(int a) = ^(int a){ NSLog(@"%zd",a); }; NSLog(@"旭宝爱吃鱼"); myBlock(999); 输出结果: 2016-05-03 11:27:18.571 block[5340:706252] 旭宝爱吃鱼

写给喜欢用Block的朋友(ios Block)

作者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/38090205 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或关注微信公众帐号fengsh998来支持我,谢谢! 本文不讲block如何声明及使用,只讲block在使用过程中暂时遇到及带来的隐性危险. 主要基于两点进行演示: 1.block 的循环引用(retain cycle) 2.去除block产生的告警时,需注意问题. 有一次,朋友问我当一个对象中的b

iOS block并发

iOS block并发 2012-06-13 09:31 1351人阅读 评论(0) 收藏 举报 iosuiviewnetwork任务threadimage 这篇文章转自 http://anxonli.iteye.com/blog/1097777,集中与iOS的多核编程和内存管理,大家完全可以使用苹果的多核编程框架来写出更加responsive的应用. 多核运算 在iOS中concurrency编程的框架就是GCD(Grand Central Dispatch), GCD的使用非常简单.它把任务

(译)IOS block编程指南 1 介绍

Introduction(介绍) Block objects are a C-level syntactic and runtime feature. They are similar to standard C functions, but in addition to executable code they may also contain variable bindings to automatic (stack) or managed (heap) memory. A block ca

ios Block学习

ios block 回调传值,回调事件, 直接上代码 在firstVC里面的tableView 点击方法 ,里面点击跳到另一个nextVC,然后返回后的firstVC后回调值 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ NextViewController *next=[[NextViewController alloc]init]; __block Nex

IOS block 教程<转>

http://pernghh.pixnet.net/blog/trackback/eac87d412e/33563409 本文来自台湾的某开发人员的博客,被墙,感觉讲的比较易懂,所以引过来.文字简体化了,原来是繁体,变数=变量,这个注意一下. 本章学习目标: 1. 了解何谓block. 2. 了解block的使用方法. Block 是iOS在4.0之后新增的程式语法,严格来说block的概念并不算是基础程式设计的范围,对初学者来说也不是很容易了解,但是在iOS SDK 4.0之后,block几乎

iOS Block界面反向传值

在上篇博客 <iOS Block简介> 中,侧重解析了 iOS Block的概念等,本文将侧重于它们在开发中的应用. Block是iOS4.0+ 和Mac OS X 10.6+ 引进的对C语言的扩展,用来实现匿名函数的特性.用维基百科的话来说,Block是Apple Inc.为C.C++以及Objective-C添加的特性,使得这些语言可以用类lambda表达式的语法来创建闭包.关于闭包,一句话解释简洁明了:闭包就是能够读取其它函数内部变量的函数. 在iOS开发中,Block有很多方面的用途,

iOS block 用法

1.定义Block /* 回传void ,参数也是void 的block*/ void (^blockReturningVoidWithVoidArgument)( void ); /* 回传整数,两个参数分别是整数和字元型态的block*/ int   (^blockReturningIntWithIntAndCharArguments)( int , char ); /* 回传void ,含有10 个block 的阵列,每个block 都有一个型态为整数的参数*/ void (^arrayO

iOS block 机制

本文要将block的以下机制,并配合具体代码详细描述: block 与 外部变量 block 的存储域:栈块.堆块.全局块 定义 块与函数类似,只不过是直接定义在另一个函数里,和定义它的那个函数共享同一个范围内的东西. 访问外部变量 堆块内部,栈是红灯区,堆是绿灯区. 根据块的存储位置,可将块分为全局块.栈块.堆块.这里先主要针对堆块讲解. Block不允许修改外部变量的值.Apple这样设计,应该是考虑到了block的特殊性,block也属于"函数"的范畴,变量进入block,实际就

# iOS Block的本质(三)

iOS Block的本质(三) 上一篇文章iOS Block的本质(二)中已经介绍过block变量的捕获,本文继续探寻block的本质. 1. block对对象变量的捕获,ARC 环境 block一般使用过程中都是对对象变量的捕获,那么对象变量的捕获同基本数据类型变量相同吗? 查看一下代码思考:当在block中访问的为对象类型时,对象什么时候会销毁? // ARC环境下代码 typedef void (^Block)(void); int main(int argc, const char *