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

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

Block语法:

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

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

例如

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

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

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

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

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

Block类型变量

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

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

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

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

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

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

截获变量值

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

    int a = ;
int (^intBlock)(int) = ^(int count){return count+a;};
NSLog(@"%d",intBlock());
-- ::53.393 Dispatch[:]

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

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

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

    __block int a = ;
int (^intBlock)(int) = ^(int count){a = ; return count+a;};
NSLog(@"%d",intBlock());
-- ::11.629 Dispatch[:]

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

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

Block循环引用

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

@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代码才行,如果不执行还是会造成内存泄露。

Objective-C—— Block的更多相关文章

  1. Objective C block背后的黑魔法

    前言 block在Objective C开发中应用非常广泛,我们知道block会捕获外部对象,也知道使用block要防止循环引用. "知其然而不知其所以然"是一件非常痛苦的事情,那 ...

  2. Automake

    Automake是用来根据Makefile.am生成Makefile.in的工具 标准Makefile目标 'make all' Build programs, libraries, document ...

  3. Objective-C( block的使用)

    block block用来保存一段代码 block的标志:^ block跟函数很像:可以保存代码.有返回值.有形参.调用方式跟调用方法一样 block内部可以访问外面的变量 默认情况下,block内部 ...

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

    一.block声明 1.无参数,无返回值: void (^sayHi)(); 2.有参数,有返回值: NSInteger (^operateOfValue)(NSInteger num); block ...

  5. Objective的字符串拼接 似乎没有Swift方便,但也可以制做一些较为方便的写法

    NSString *str1 = @"字符串1"; NSString *str2 = @"字符串2"; //在同样条件下,Objective的字符串拼接 往往只 ...

  6. Objective C ARC 使用及原理

    手把手教你ARC ,里面介绍了ARC的一些特性, 还有将非ARC工程转换成ARC工程的方法 ARC 苹果官方文档 下面用我自己的话介绍一下ARC,并将看文档过程中的疑问和答案写下来.下面有些是翻译,但 ...

  7. iOS Block详细介绍(block实现)

    Block的实现 数据结构定义 block的数据结构定义如下图 对应的结构体定义如下: struct Block_descriptor { unsigned long int reserved; un ...

  8. @weakify, @strongify ObjC的Block中使用weakSelf/strongSelf @weakify/@strongify

    首先要说说什么时候使用weakSelf和strongSelf. 下面引用一篇博客<到底什么时候才需要在ObjC的Block中使用weakSelf/strongSelf>的内容: Objec ...

  9. 堆block和栈block的区分

    0. 问题所在 下面给出一段代码: - (NSArray*) getBlockArray { int num = 916; return [[NSArray alloc] initWithObject ...

  10. ObjC的Block中使用weakSelf/strongSelf @weakify/@strongify

    首先要说说什么时候使用weakSelf和strongSelf. 下面引用一篇博客<到底什么时候才需要在ObjC的Block中使用weakSelf/strongSelf>的内容: Objec ...

随机推荐

  1. HTML学习笔记之标签进阶

    目录 1.框架 2.表单 3.音频 4.视频 5.文档类型 6.头部元素 7.样式 8.脚本 9.实体 1.框架 使用框架允许我们在同一个浏览器窗口中显示多个页面,其中每份 HTML 文档称为一个框架 ...

  2. Sessions共享技术设计

    概述 分布式session是实现分布式部署的前提, 当前项目由于历史原因未实现分布式session, 但是由于在kubernets中部署多个pod时, 负载均衡的调用链太长, 导致会话不能保持, 所以 ...

  3. 1、深度学习模型的基本结构——RNN

    本系列为深度学习课程笔记,课程网址在http://speech.ee.ntu.edu.tw/~tlkagk/courses_MLDS17.html 深度学习的基本步骤:定义模型-->定义损失函数 ...

  4. controller 接口写法

    import org.apache.commons.io.IOUtils; import javax.servlet.ServletInputStream; @RequestMapping(" ...

  5. SSM框架下实现导出功能

    导出:将当前页面表格里值传到excel表格中. 一.页面js //下载excel $("#download").click( function() { var param = $( ...

  6. python浅拷贝与深拷贝

    今天写程序,人为制造了一个由浅拷贝引起的bug,有必要归纳一下.先附上源代码: class PerformanceTest(object): def __init__(self): ....... s ...

  7. HDU - 1403 - Longest Common Substring

    先上题目: Longest Common Substring Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/32768 K ...

  8. RDS for MySQL Online DDL 使用

    https://help.aliyun.com/knowledge_detail/41733.html?spm=5176.7841698.2.17.u67H3h

  9. pthread2

    下面我们来看看这个demo #include <stdio.h> #include <pthread.h> #include <unistd.h> #include ...

  10. 微信小程序的小问题(1)

    1. imgUrls: [ '../../images/index/banner1.jpg', '../../images/index/banner2.jpg', '../../images/inde ...