首先,什么是block?block其实就是一个代码块,把你想要执行的代码封装在这个代码块里,等到需要的时候再去调用。那block是OC对象吗?答案是肯定的。

做一道很简单的关于block的测试题:

int (^testBlock)
(int) = ^(int num) {
return num++;
};
NSLog(@"%d", testBlock(testBlock(testBlock())
));

这道题是我公司面试题中的一道,来面试的都是至少两年工作经验的,但是很郁闷,这道题绝大多数人写的都是6。。正确结果为:3。

以下讲解的内容均是ARC环境下。

一、block的分类

  • NSStackBlock:栈block

  • NSMallocBlock:堆block

  • NSGlobalBlock:全局block

1.NSStackBlock:

特点:生命周期由系统控制,函数返回即销毁

用到局部变量、成员属性\变量,且没有强指针引用的block都是栈block

int (^testBlock)
(int) = ^(int num) {
return num++;
};
NSLog(@"%d", testBlock(testBlock(testBlock())
));

注意:不是没有强指针(copy或strong)引用的block,就是栈block,也有可能是全局block(下面会介绍什么是全局block)。

2.NSMallocBlock:

特点:没有强指针引用即销毁,生命周期由程序员手动管理
栈block如果有强指针引用或copy修饰的成员属性引用就会被拷贝到堆中,变成堆block

//堆block
int j = ;
void(^mallocBlock)() = ^ {
NSLog(@"%d",j);
};
NSLog(@"%@",mallocBlock);
//输出结果 <__NSMallocBlock__: 0x7f8cd351db80>

上面代码也没用看到strong 或 copy修饰符,但是为什么会强引用的,因为在ARC环境下,我们在声明变量的时候,前面是会被默认加上 __strong 修饰符的。所以我们在ARC下声明的Block一般都是堆block。

3.NSGlobalBlock:

特点:命长,有多长?很长很长,人在塔在(应用程序在它就在)

没有用到外界变量,或者只用到全局变量、静态(static)变量的block就是全局block

对于全局block,用weak,strong,还是copy修饰都是可以的。(但最好不用用weak)

//全局block
void (^globalBlock) () = ^ {
NSLog(@"%d",staticNum);
};
NSLog(@"%@",globalBlock);
//输出结果 <__NSGlobalBlock__: 0x108152110>

注意:如果block中没有用到外界变量,不管他是用什么修饰符修饰,他都是全局block!

例如:

void (^global2Block) () = ^ {
NSLog(@"globalBlock");
};
NSLog(@"%@",global2Block); // 输出结果 <__NSGlobalBlock__: 0x1023a0150>

二、block对外界变量的捕获

1.1 基本数据类型:局部变量

block会拷贝该变量的值当做常量使用,外界修改变量的值不会影响block内部,且block内部不能对其修改

block内部修改外界变量i的值直接报错,如果想要修改,可以在int a = 0前面加上关键字__block,此时i等效于全局变量或静态变量

int a = ;
void (^block1)() = ^ {
NSLog(@"a = %d",a);
};
a++;
block1(); //输出结果 a = 0;
__block int b = ;
void (^block2) () = ^ {
NSLog(@"b = %d",b); // 输出结果 b = 0;
b = ;
};
block2();
NSLog(@"b = %d",b); //输出结果 b = 2;

1.2 基本数据类型:成员变量(实例变量),静态变量,全局变量

block直接访问变量地址,在block内部可以修改变量的值,并且外部变量被修改后,block内部也会跟着变

self.num = ;
self.num ++; void (^block3) () = ^ {
self.num++;
};
block3();
NSLog(@"%d",self.num);
//输出结果为 3

2.1 指针类型: 局部变量

block会复制一份指针并强引用指针所指对象,且内部不能修改指针的指向,但是可以修改指针所指向对象的值

NSMutableString *str = @"abc".mutableCopy;
void (^block4) () = ^ {
// str = @"def"; 报错
[str appendString:@"def"];
NSLog(@"str = %@",str);
};
str = @"".mutableCopy;
block4(); //输出结果为 "adbdef"

2.2 指针类型: 成员变量(实例变量),静态变量,全局变量

block不会复制指针,但是会强引用该对象,内部可修改指针指向,block会强引用成员属性\变量所属的对象,这也是为什么block内部用到self.xxx或_xxx可能会引起循环引用的原因

static NSString *staticStr = @"abc";
void (^block5) () = ^ {
NSLog(@"staticStr = %@",staticStr);
staticStr = @"def";
NSLog(@"staticStr = %@",staticStr);
};
staticStr = @"";
block5(); //输出结果为 staticStr = 123 staticStr = def

深入学习block的更多相关文章

  1. iOS开发-由浅至深学习block

    关于block 在iOS 4.0之后,block横空出世,它本身封装了一段代码并将这段代码当做变量,通过block()的方式进行回调.这不免让我们想到在C函数中,我们可以定义一个指向函数的指针并且调用 ...

  2. ruby学习--block

    #当前块 class Block def a_method return yield if block_given? 'no block' end end obj=Block.new puts &qu ...

  3. 深入学习 Block

    本文翻译自苹果的文档,有删减,也有添加自己的理解部分. 如果有Block语法不懂的,可以参考fuckingblocksyntax,里面对于Block 为了方便对比,下面的代码我假设是写在ViewCon ...

  4. 原 iOS深入学习(Block全面分析)http://my.oschina.net/leejan97/blog/268536

    原 iOS深入学习(Block全面分析) 发表于1年前(2014-05-24 16:45)   阅读(26949) | 评论(14) 39人收藏此文章, 我要收藏 赞21 12月12日北京OSC源创会 ...

  5. IOS学习4——block代码块

    本文转载自:iOS开发-由浅至深学习block 一.关于block 在iOS 4.0之后,block横空出世,它本身封装了一段代码并将这段代码当做变量,通过block()的方式进行回调.这不免让我们想 ...

  6. 浅谈 block(1) – clang 改写后的 block 结构

    这几天为了巩固知识,从 iOS 的各个知识点开始学习,希望自己对每一个知识理解的更加深入的了解.这次来分享一下 block 的学习笔记. block 简介 block 被当做扩展特性而被加入 GCC ...

  7. OC block的简单使用

    http://blog.csdn.net/itpeng523/article/details/23965147 一.先用Xcode创建一个空工程 学习block之前先用弄懂c语言的函数指针 看代码: ...

  8. IOS学习3——代理

    本文转载自:你真的了解iOS代理设计模式吗? 在项目中我们经常会用到代理的设计模式,这是iOS中一种消息传递的方式,也可以通过这种方式来传递一些参数.这篇文章会涵盖代理的使用技巧和原理,以及代理的内存 ...

  9. Linux kernel学习-内存管理【转】

    转自:https://zohead.com/archives/linux-kernel-learning-memory-management/ 本文同步自(如浏览不正常请点击跳转):https://z ...

随机推荐

  1. (一)学习C#之浮点类型float小结

    类型:float 大小:32位 范围a:±3.4E38  MSDNhttp://msdn.microsoft.com/zh-cn/library/b1e65aza.aspx 范围b: ±1.5E45~ ...

  2. [转] ArcEngine中打开各种数据源(WorkSpace)的连接

    原文 ArcEngine中打开各种数据源(WorkSpace)的连接(SDE.personal/File.ShapeFile.CAD数据.影像图.影像数据集) ArcEngine 可以接受多种数据源. ...

  3. Codeforces 611C New Year and Domino DP+容斥

    "#"代表不能放骨牌的地方,"."是可以放 500*500的矩阵,q次询问 开两个dp数组,a,b,a统计横着放的方案数,b表示竖着放,然后询问时O(1)的,容 ...

  4. 如何制作网页小动画?——gif or png

    一.场景与动画 为了拉动网站氛围,或者吸引用户浏览焦点,需要使用一些小动画.这种动画不是(gif)单纯的重复,而是需要需要一些控制和交互,比如在动画完成后打开一个对话框.动画有几个基本要素(时间控制, ...

  5. SQL Server 用表中已有数据造数据

    从表中选择数据再插入到表中(select XXX into 与insert into XXX select的结合) 在做性能测试时需要大量的业务数据.完全从画面造数据比较费时间,使用SQL文批量插入数 ...

  6. A Tour of Go Advanced Exercise: Complex cube roots

    Let's explore Go's built-in support for complex numbers via the complex64 and complex128 types. For ...

  7. iOS语音播放之切换听筒和扬声器的方法解决方案

    关于流媒体播放的相关知识可以加本人QQ:564702640 一起来讨论 [[UIDevice currentDevice] setProximityMonitoringEnabled:YES]; // ...

  8. Linux web工程部署远程必备软件安装

    一.序 最近在将程序往linux上面部署,特此记录下部署步骤,待以后参考. web工程部署必备软件为:JDK.tomcat.数据库软件(oracle或mysql),远程监控.上传下载必备软件:VNC. ...

  9. MongoDB系列一(安装)

    一.MongoDB在Windows平台下的安装: 安装包官方下载地址:http://www.mongodb.org/downloads 第一步:下载安装包:如果是win系统,注意是64位还是32位版本 ...

  10. android 数据存储操作之SQLite

    一. SQLite介绍 SQLite是android内置的一个很小的关系型数据库. 二. SQLiteOpenHelper的使用方法 ①SQLiteOpenHelper是一个辅助类来管理数据库的创建和 ...