Objective-C—— Block

OC Block 其实功能就类似C语言的函数指针,js中的闭包之类的。把代码块当做一个变量就行操作,有自己的变量和作用域。

简单看一下Block的语法和可能出现的问题:

Block语法:

block语法相对宽松,很多部分都可以省略,常规上我们实现一个block需要有以下几个部分

^ 返回值类型 参数列表 表达式

例如

    ^int (int count){return count+1;};//返回值为int 参数为int 表达式为 count+1;
    ^void (void){NSLog(@"void");};    //返回值为void 参数void 表达式为  NSLog(@"void");

可以看到语法相对简单,而且返回值类型可以省略那么以上两个block就变

    ^(int count){return count+1;};
    ^(void){NSLog(@"void");};

如果不适用参数,那么返回值列表也可以省略

    ^(int count){return count+1;};
    ^{NSLog(@"void");};

Block类型变量

Blcok类型的变量可以接受对应的Block,上例中两个Block就需要以下两种Block类型变量接收

    int (^intBlock)(int) = ^(int count){return count+1;};
    void (^voidBlock)(void) = ^{NSLog(@"void");};

上例中,可以看到变量定义格式

返回值类型 (^变量名称) (返回值类型)

如果嫌这种定义方式麻烦的话,可以使用typedef来简化定义方式

    typedef int (^typedefBlock) (int);
    typedefBlock block = ^(int count){return count+1;};

截获变量值

Block中,可以使用调用Block之前的变量的值,例如

    int a = 5;
    int (^intBlock)(int) = ^(int count){return count+a;};
    NSLog(@"%d",intBlock(5));
    2015-08-02 17:25:53.393 Dispatch[9970:3096937] 10

可以看到输出结果是10,说明intBlock截获了变量a的值。

但是如果我们想要修改a的值,就会出现错误可以自己尝试一下。

想要修改需要在变量前添加__block修饰符,说明该变量在block中是可以被修改的。

    __block int a = 5;
    int (^intBlock)(int) = ^(int count){a = 3; return count+a;};
    NSLog(@"%d",intBlock(5));
    2015-08-02 17:33:11.629 Dispatch[10118:3136172] 8

输出结果为8,说明已经被我们修改了。

同样的道理,对已OC对象来说也是,如果调用方法使用该变量可以,但是对变量进行赋值操作就需要加上__block修饰符。

Block循环引用

循环引用出现条件,该对象持有Block的成员属性,同时在Block中使用self。这样会造成Block和对象之间的相互引用,互相都无法释放,形成内存泄露。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

@interface ViewController ()

{

    voidBlock _voidBlock;

}

- (void)viewDidLoad {

    [super viewDidLoad];

    

   // __block int a = 5;

    _voidBlock = ^{NSLog(@"%@",self);};

    _voidBlock();

}

这样写编译去会提示我们self的强引用在Block中使用。

还有一种,如果我们在Block中使用了成员属性,同样会造成内存泄露。因为成员属性是self指针指向的对象,还是在Block中持有了self。

__weak
为了避免这样的情况发生,我们再上面的例子中稍微修改一下

- (void)viewDidLoad {
    [super viewDidLoad];

   // __block int a = 5;
    __weak ViewController *temp = self;
    _voidBlock = ^{NSLog(@"%@",temp);};
    _voidBlock();

}

使用弱引用对象就能很好的避免这种情况。

再有就是用__block也能够避免循环。

- (void)viewDidLoad {
    [super viewDidLoad];

   // __block int a = 5;
    __block ViewController *temp = self;
    _voidBlock = ^{NSLog(@"%@",temp); temp = nil;};
    _voidBlock();

}

注意这样写必须调用该Block,执行Block代码才行,如果不执行还是会造成内存泄露。

时间: 2024-08-06 19:10:10

Objective-C—— Block的相关文章

Objective C block背后的黑魔法

前言 block在Objective C开发中应用非常广泛,我们知道block会捕获外部对象,也知道使用block要防止循环引用. "知其然而不知其所以然"是一件很痛苦的事情,那么block这套机制在OC中是如何实现的呢?本文通过从C/C++到汇编层面分析block的实现原理. Clang clang是XCode的编译器前端,编译器前端负责语法分析,语义分析,生成中间代码(intermediate representation ). 比如当你在XCode中进行build一个.m文件的时

CSDN日报20170417 ——《程序员最好有 社保》

[程序人生]程序员最好有 社保 作者:郭小北 这个话题,其实是个社会性问题,虽说我很帅,但这种话题一般我很少公开讨论.但最近发现不少朋友因为社保的问题,办事卡壳,导致耽误了很多重要的事,他们很后悔,很无奈. [深度学习]TensorFlow实现基于深度学习的图像补全 作者:寒小阳 在这篇博客中,我会介绍 Raymond Yeh 和 Chen Chen 等人的一篇论文,"基于感知和语境损失的图像语义修补(Semantic Image Inpainting with Perceptual and C

初学Objective - C语法之代码块(block)

一.block声明 1.无参数,无返回值: void (^sayHi)(); 2.有参数,有返回值: NSInteger (^operateOfValue)(NSInteger num); block的声明:返回值类型(^block变量名)(参数列表) 脱字符(^)是块的语法标记 二.block实现 block变量名 = ^返回值类型(参数列表) 1.  sayHi = ^{ NSLog(@"你好"); }; 2. operateOfValue = ^ NSInteger (NSInt

Objective-C( block的使用)

block block用来保存一段代码 block的标志:^ block跟函数很像:可以保存代码.有返回值.有形参.调用方式跟调用方法一样 block内部可以访问外面的变量 默认情况下,block内部不能修改外面的局部变量 给局部变量加上__block关键字,这个局部变量就可以在block内部修改 利用typedef定义block类型 typedef int (^MyBlock)(int, int); 以后就可以利用MyBlock这种类型来定义block变量 MyBlock block; MyB

Block 简介

1.Blocks简介 Block字面意思就是代码块 iOS4.0.Mac OS X 10.6开始Apple引入的特性 Block是Objective C语言中的对象 但是与NSObject有所区别 Block是特殊的Objective C对象 Block 对象提供了一个使用 C 语言和 C 派生语言(如 Objective-C 和 C++)来创建表达式作为一个特别的函数.在其他语言和环境中,一个block对象有时候被称为“闭包(closure)”.在这里,它们通常被口语化为”块(blocks)”

iOS完全自学手册——[三]Objective-C语言速成,利用Objective-C创建自己的对象

1.前言 上一篇已经介绍了App Delegate.View Controller的基本概念,除此之外,分别利用storyboard和纯代码创建了第一个Xcode的工程,并对不同方式搭建项目进行了比较.这一篇文章,我准备为大家介绍一下奇葩的Objective-C语言的语法和使用.这篇文章主要讲Objective-C的理论概念. 2.学习目标 2.1 Objective-C语言面向对象的特性与其他语言(C++)类比学习,声明定义一个MyObject类,并创建这个类的实例. 2.2 Objectiv

iOS开发核心语言Objective C —— 全部知识点总结

本分享是面向有意向从事iOS开发的伙伴及苹果产品的发烧友,亦或是已经从事了iOS的开发人员,想进一步提升者.假设您对iOS开发有极高的兴趣,能够与我一起探讨iOS开发.一起学习,共同进步.假设您是零基础.建议您先翻阅我之前分享的iOS开发分分钟搞定C语言系列,然后在開始Objective C语言的学习,假设您遇到问题也能够与我探讨.另外将无偿分享自己整理出来的大概400G iOS学习视频及学习资料,都是干货哦.能够新浪微博私信?关注极客James,期待与您的共同学习和探讨! ! 由于时间有限,每

深入理解ObjetiveC的Block

0. 问题所在 下面给出一段代码: - (NSArray*) getBlockArray { int num = 916; return [[NSArray alloc] initWithObjects: ^{ NSLog(@"this is block 0:%i", num); }, ^{ NSLog(@"this is block 1:%i", num); }, ^{ NSLog(@"this is block 2:%i", num); },

Objective C ARC 使用及原理

手把手教你ARC ,里面介绍了ARC的一些特性, 还有将非ARC工程转换成ARC工程的方法 ARC 苹果官方文档 下面用我自己的话介绍一下ARC,并将看文档过程中的疑问和答案写下来.下面有些是翻译,但不是全部,请一定要看一遍官方文档 不考虑 iOS4 的 ARC 规则 简单地说,ARC在编译时刻为代码在合适的位置加上retain 和 release. 复杂点,它还提供其它一些功能,还为解决一些问题,添加了一些关键字和功能,后面会说. ARC强制要求的新规则 不可以调用dealloc, 不可以实现

堆block和栈block的区分

0. 问题所在 下面给出一段代码: - (NSArray*) getBlockArray { int num = 916; return [[NSArray alloc] initWithObjects: ^{ NSLog(@"this is block 0:%i", num); }, ^{ NSLog(@"this is block 1:%i", num); }, ^{ NSLog(@"this is block 2:%i", num); },