原文参考博文:

http://blog.devtang.com/2013/07/28/a-look-inside-blocks/

http://www.cnblogs.com/kesalin/archive/2013/04/30/ios_block.html

block 实际上可以理解成是Objective-C 语言对于闭包的实现。配合上 dispatch_queue,可以方便地实现简单的多线程编程和异步编程。

关于闭包,可以理解成是一个函数(或指向函数的指针),再加上该函数执行的外部的上下文变量。

这里介绍关于block的:

1,内部实现,数据结构介绍

2,block 的三种类型及其相关的内存管理方式

3,block 如何通过 capture 变量来达到访问函数外的变量

一个 block 实际是一个对象,它主要由一个 isa 和 一个 impl 和 一个 descriptor 组成。更具体的说来,结构如下:

对应的结构体定义如下,

struct Block_layout {
void *isa;
int flags;
int reserved;
void (*invoke)(void *, ...);
struct Block_descriptor *descriptor;
/* Imported variables. */
};
struct Block_descriptor {
unsigned long int reserved;
unsigned long int size;
void (*copy)(void *dst, void *src);
void (*dispose)(void *);
};

可以看出,主要包含6部分,

1,isa指针,所有对象都有这个指针。指向对象的类结构。

2,invoke指针,函数指针,指向具体的block实现的函数调用地址

3,variables,block 能够访问它外部的局部变量,就是因为将这些变量(或变量的地址)复制到了结构体中。

4,reserved,保留字段。5,flags,descriptions,一些附加描述信息,比如size等。

OC中,一共三种类型的block,

1,_NSConcreteGlobalBlock 全局的静态 block,不会访问任何外部变量。

2,_NSConcreteStackBlock 保存在栈中的 block,当函数返回时会被销毁。

3,_NSConcreteMallocBlock 保存在堆中的 block,当引用计数为 0 时会被销毁。

block对外部变量的引用:

主要包含2类,

1,对于 block 外的变量引用,block 默认是将其复制到其数据结构中来实现访问的。

2,对于用 __block 修饰的外部变量引用,block 是复制其引用地址来实现访问的。

=======

block使用时的几个注意点:

1,block中的变量拷贝,是在实现时,对引用到的它所在方法中定义的栈变量进行一次只读拷贝。

这个变量是只读的,比如

id result = nil;

[context performBlockAndWait:^{

result = block();

}];

会报错,variable is not assignable。

需要对其有写操作时,可以加__block。

2,非内联(inline)block 不能直接访问 self。

  这种情况,可以将self 当作参数传递到 block 中才能使用。而且这个时候self的属性,只能通过setter 或 getter方法访问,不能用点语法。

typedef NSString* (^IntToStringInlineConverter)(NSInteger paramInteger);

// 非内联block

IntToStringConverter independentBlockObject = ^(id self, NSInteger paramInteger) {
    KSLog(@" >> self %@, memberVariable %d", self, [self memberVariable]);
NSString *result = [NSString stringWithFormat:@"%d", paramInteger];
KSLog(@" >> independentBlockObject %@", result);
return result;
};

// 内联block,用到self则不需要传self,也可以用点语法。
- (void)testAccessSelf
{
// Independent
[self convertIntToString:20 usingBlockObject:independentBlockObject]; // Inline
IntToStringInlineConverter inlineBlockObject = ^(NSInteger paramInteger) {
KSLog(@" >> self %@, memberVariable %d", self, self.memberVariable);
NSString *result = [NSString stringWithFormat:@"%d", paramInteger];
KSLog(@" >> inlineBlockObject %@", result);
return result;
};
[self convertIntToStringInline:20 usingBlockObject:inlineBlockObject];
}

3,使用 weak–strong避免循环引用

  内联block直接使用self时,需要小心,避免循环引用。

  block的本质其实还是一个对象。当self强持有这个block,而这个block又强持有self时,就会导致循环引用。

  换句话也就是说,只有释放了self才可以释放被self强持有的block。但self又被block强持有,无法释放。

  

  __weak KSViewController * wself = self;
_observer = [[NSNotificationCenter defaultCenter]
addObserverForName:@"TestNotificationKey"
object:nil queue:nil usingBlock:^(NSNotification *n) {
KSViewController * sself = wself;
if (sself) {
NSLog(@"%@", sself);
}
else {
NSLog(@"<self> dealloc before we could run this code.");
}
}];

  weak-strong的作用是,

  外部传入一个self的弱引用。这样block对象并没有强持有self,当self被释放的时候,wself 变成 nil。这样已经可以解决循环引用的问题。

  但是为了在block运行过程中不至于出现wself被释放,所以一般会声明一个__strong的变量,持有wself。这样,在self被释放后,block可以本正常释放,sself也就被释放。

【引】objective-c,3:关于block的更多相关文章

  1. Objective-C( block的使用)

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

  2. Automake

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

  3. Swift正在使用NSURLConnection异步下载同步(实例解析)

    原版的blog.转载请注明出处 http://blog.csdn.net/hello_hwc 一.同步异步两个概念 简单来讲.同步就是函数或者闭包(objective c中的block)运行完成才干返 ...

  4. 完整详细的说明GCD列(一)dispatch_async;dispatch_sync;dispatch_async_f;dispatch_sync_f

    为什么要写这个系列,由于百度了一下.我们正在寻找一个非常比较片面的Blog.抄来抄去,写作是很粗糙. 所以,我想写这个系列,尝试记录官方网站GCD强大的全功能的表达.为了方便他们,也方便他人,假设有发 ...

  5. Objective C block背后的黑魔法

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

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

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

  7. Objective C中的ARC的修饰符的使用---- 学习笔记九

    #import <Foundation/Foundation.h> @interface Test : NSObject /** * 默认的就是__strong,这里只是做示范,实际使用时 ...

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

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

  9. Objective C ARC 使用及原理

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

随机推荐

  1. HalconMFC(三)之打开图像_简单处理

    在VS2010中配置完halcon之后就得写个最简单的程序满足一下咱们的自信心呀! 第一步,新建MFC程序 最好是按照下面这么设置然后点击"完成",就不会报错 第二步,导出C++代 ...

  2. Java中获取长度length和size的问题

    1.length属性是针对Java中的数组来说的,要求数组的长度可以用其length属性: 2.length()方法是针对字符串来说的,要求一个字符串的长度就要用到它的length()方法: 3.ja ...

  3. 执行时关闭标识位 FD_CLOEXEC 的作用

    首先先回顾 apue 中对它的描述: ① 表示描述符在通过一个 exec 时仍保持有效(书P63,3.14节 fcntl 函数,在讲 F_DUPFD 时顺便提到) ② 对打开文件的处理与每个描述符的执 ...

  4. 【转】tomcat7性能调优

    注意:调优tomcat需要了解使用的tomcat是什么版本,随着tomcat版本发展有新参数引入,同时有旧参数废弃.本文档以tomcat7为例进行调优 一. 线程池(Thread Pool)优化 编辑 ...

  5. util-linux编译unknown architecture 'BSD_LABELSECTOR' undeclared错误

    ------------------------------------------------------------------------------ In :: fdiskbsdlabel.h ...

  6. Nginx+Tomcat构建动、静分离WEB架构

    一.简介 二.环境介绍 三.后端服务器安装配置 四.安装论坛 五.安装配置前端Nginx服务器 六.验证服务 一.Tomcat简介 Tomcat是Apache 软件基金会(Apache Softwar ...

  7. 例子:Backup Isolated Storage To SkyDrive

    本例演示了如何从隔离存储中备份文件到SkyDrive. 1. 登陆微软网站,申请“Create application”,获取一个“Client ID” 2. XAML中添加对Live相关控件库的命令 ...

  8. boxsizing属性 IE盒模型和标准盒模型

    CSS3有一个非常有用但应用不广泛的属性: box-sizing: content-box | border-box | inherit content-box,默认属性,遵从标准盒模型. borde ...

  9. 我是一只IT小小鸟读后感

    当老师推荐我读这本书的时候,并不想看,因为我不喜欢机械的东西,然而阅读几章后,对这本书有了其他看法.不知不觉竟把它看完!看完这本<我是一只IT小小鸟>,我感触很深. 在书中我明白了很多,大 ...

  10. 第六篇——初尝Python,意犹未尽

    作业2的要求是选一个你从来没有学过的编程语言,试一试实现基本功能.那么在这里我准备学习Python语言进行学习,并尝试用Python写一写东西. http://www.runoob.com/ Pyth ...