>>定义并使用一个block    返回值(^名字)(参数列表) =^返回值类型(参数列表){表达式};  其中返回值和参数列表可以神略 ,最简单的block是  ^{xxxx};

void(^add)(int a , int b ) = ^(int a , int b ){

NSLog(@"a+b=%d",a+b);

};

add(1,3);

>>假设有如下代码

- (void)viewDidLoad {

int f = 0;

void(^add)(int a , int b ) = ^(int a , int b ){

NSLog(@"a+b=%d",a+b);

f = 1;

};

add(1,3);

}

这个时候,会提示f=1;这里出现错误,如果需要修改block以外的局部变量(在这个viewDidLoad函数内的)就需要使用 __block int f = 0;

不需要加入__block就可以直接修改的变量(从下面看出,应该就是变量的生命周期问题)(注释1)

全局变量

类的成员变量

static变量(函数体里面也可以的)

>>有如下代码

int a = 1;

void(^OutPut)() = ^(){

NSLog(@"a=%d",a);

};

a = 2;

OutPut();

上面的代码输出 a=1;

如果修改为 __block int a = 1;   这样会输出 a=2;(所有的可改变的变量都会输出2,在上面注释1处说明的变量)

>>再看一个例子

- (void)viewDidLoad {

NSMutableArray * arr = [NSMutableArray arrayWithObject:@"ddd"];

void(^OutPut)() = ^(){

[arr removeLastObject];

arr = [NSMutableArray new];

};

OutPut();

}

上面提到比如不加入__block的变量是不能在block里面修改的,这里的arr因为没有加__block 所以在执行 arr = [NSMutableArray new];的时候就出错了,但是[arr removeLastObject];并没有任何问题。

>>定义一个 Block Pointer

上面的 void(^add)(inta,int b) 我们其实可以使用一个typedef来实现

typedef void(^AddMethod)(int , int );

AddMethod add = ^(int a , int b ){ NSLog(@“a+b=%d”,a+b};

下面涉及到的内容可以看看如下网址

http://www.cocoachina.com/bbs/read.php?tid=152222

>>NSStackBlock  NSGlobalBlock NSMallocBlock 如何区分(可以通过NSLog来打印出一个block属于哪个类型)

NSGlobalBlock:

block内不访问任何变量的

block除了方位全局变量跟static变量的(其中类的成员变量等不在这2种类型里面)

剩下的基本上都是StackBlock

比如:

void(^outPut)() = ^{

NSLog(@"outPut");

};

是GlobalBlock,因为block内部没有访问任何变量

比如:

int a = 0;

void(^outPut)() = ^{

NSLog(@"outPut:%d",a);

};

是StackBlock,因为方位了非(全局,static)变量

比如:

static int a = 0;

void(^outPut)() = ^{

NSLog(@"outPut:%d",a);

};

是GlobalBlock,因为只访问了static变量

>> 有了上面3个Block存储区域的概念,我们就比较容易理解了下面的内容了。

例子:

  • void exampleB_addBlockToArray(NSMutableArray *array) {
  • char b = 'B';
  • [array addObject:^{
  • printf("%c\n", b);
  • }];
  • }
  • void exampleB() {
  • NSMutableArray *array = [NSMutableArray array];
  • exampleB_addBlockToArray(array);
  • void (^block)() = [array objectAtIndex:0];
  • block();
  • }

首先看addObject这个block是一个StackBlock

在ARC情况下,执行正确 :因为ARC下会自动将StackBlock拷贝到MallocStack中

在非ARC情况下,执行错误:因为在exampleB_addBlockToArray函数返回之后,这个block失效了

例子

  • void exampleC_addBlockToArray(NSMutableArray *array) {
  • [array addObject:^{
  • printf("C\n");
  • }];
  • }
  • void exampleC() {
  • NSMutableArray *array = [NSMutableArray array];
  • exampleC_addBlockToArray(array);
  • void (^block)() = [array objectAtIndex:0];
  • block();
  • }

首先看这里的addObject这个block没有访问任何的外部变量,所以这是一个GlobalBlock,不管在ARC还是非ARC下,都是正确的。

>>  为什么在使用property属性修饰block的时候,需要用到copy操作?

在非ARC下,需要将block从栈中copy到堆中,避免被自动释放。对block 进行retain操作是无效的

在ARC下,block会自动copy到堆中。

>> Block循环引用问题(一定要是双方的)

使用block的时候,经常会由于循环引用的问题导致内存无法释放,(对象拥有block,block又用到对象)

比如

self.myBlock = ^{ [self xxxxx];};

这里myBlock是self的属性,而在myBlock里面又使用到了self;self在释放的时候必定要先释放myBlock,但是myBlock需要先释放里面的self,这样就导致死循环了。

要打破这个格局,可以使用如下

在ARC下:

__weak typeof(self) weakSelf = self;

self.myBlock = ^{ [weakSelf xxxxx];};

如果在block里面会多次用到weakSelf 那应该使用如下的strongSelf

__weak typeof(self) weakSelf = self;

self.myBlock = ^{

__strong typeof(self)strongSelf = weakSelf;

[strongSelf xxxxx];

[strongSelf bbbbb];

};

在非ARC下,直接将__weak改为__block就可以(__block typeof(self)weakSelf=self;)。

所以__block的意思在ARC下只表示可修改;在非ARC下,表示可修改、不要retain这个变量.

>> 在一个类中,并不是直接使用了self才会导致强引用self的。比如类中有一个实例变量 int value;

那么在  dispatch_async(queue,^{    doSomthingWith(value); } );   这个时候用到了类的实例变量value,实际上也是强应用了 self。如果queue是类的成员变量,那就会出现死循环的问题。如果是这样  dispatch_async(dispatch_get_global_queue(0,0),^{    doSomthingWith(value); } ); 这个就是单向引用,不会造成死循环。

>>  block与函数的区别

block是对象,它封装了一段代码,这段代码可以在任何时候执行。block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或者返回值。

block跟传统的函数指针很类似,但是block是内联的(inline),并且它对局部变量只是只读的。

block可以访问局部变量,但是不能修改

在需要修改的局部变量前加入__block

定义一个block看上去像定义一个函数差不多,void(^bbb)(void)=^(int a){…..};

但是还是有很大的区别的,block的定义可以在一个函数的内部实现。

>> __block 与 __weak的区别

__block 在ARC以及MRC模式下都可以使用。

__weak是ARC模式下使用的,代表的是弱引用,防止循环引用。

__block在非ARC下表示可以修改、如果修饰的是对象,表示不要retain(防止循环引用)

__block对象在block中可以被重新赋值,__weak不可以。

BLOCK专题的更多相关文章

  1. ios专题 -block用法

    what is block Blocks are a language-level feature added to C, Objective-C and C++, which allow you t ...

  2. [.NET领域驱动设计实战系列]专题八:DDD案例:网上书店分布式消息队列和分布式缓存的实现

    一.引言 在上一专题中,商家发货和用户确认收货功能引入了消息队列来实现的,引入消息队列的好处可以保证消息的顺序处理,并且具有良好的可扩展性.但是上一专题消息队列是基于内存中队列对象来实现,这样实现有一 ...

  3. Block Chain, a protocol view

    我做了个区块链的文档,给自己扫盲用的,有兴趣的可以看下,主要是自己画示意图比较好理解,示意图之后的专题部分,内容直接取自参考链接.网上的资料都是谈区块链有什么性质.有什么能力.有什么应用之类的,我主要 ...

  4. block的内部实现

    主要内容: 一.block相关的题目 二.block的定义 三.block的实现 四.捕获自动变量值 五.block存储区域 六.截获对象 一.block相关的题目 这是一篇比较长的博文,前部分是bl ...

  5. 【转】css学习专题-BFC

    css学习专题-BFC 转自:原文链接:css学习专题-BFC文章目录 BFC:Block Formatting Context. BFC就是一种布局方式,在这种布局方式下,盒子们自所在的 conta ...

  6. HBase 专题技术收录

    HBase系列: 博客地址:http://www.cnblogs.com/panfeng412/tag/HBase/ 技术专题文章: HBase中MVCC的实现机制及应用情况 HBase在单Colum ...

  7. CSS浮动专题!

    在css中,浮动问题可能是很多刚入门的小白比较头疼的问题. 1,首先先来介绍一下两种浮动类型:左浮动和右浮动 1) float:left;左浮动,后面的内容会流向对象的右侧 2) float:righ ...

  8. mysql优化专题」90%程序员都会忽略的增删改优化(2)

    补充知识点:操作数据语句优化的认识 通常情况下,当访问某张表的时候,读取者首先必须获取该表的锁,如果有写入操作到达,那么写入者一直等待读取者完成操作(查询开始之后就不能中断,因此允许读取者完成操作). ...

  9. Oracle之SQL优化专题01-查看SQL执行计划的方法

    在我2014年总结的"SQL Tuning 基础概述"中,其实已经介绍了一些查看SQL执行计划的方法,但是不够系统和全面,所以本次SQL优化专题,就首先要系统的介绍一下查看SQL执 ...

随机推荐

  1. Floodlight中的临时流表

    运行Floodlight,在Mininet中新建一个拓扑之后,并未添加相关的流表项,但是主机之间却可以相互通信.执行pingall操作,任意两个主机之间都能通.相当于没有任何路由表的路由器,它是怎么让 ...

  2. springmvc环境的搭建

    最近应公司要求,用了2天时间学了springmvc的搭建,就简单总结一下: springmvc和struts2的比较,因为我是学过struts的,它们都是基于mvc模式而设计的web层框架 它们最大的 ...

  3. 是谁决定了走redis缓存?当然是mybatis啊

    1.是谁决定了走redis缓存?当然是mybatis啊 mybatis里默认实现数据的增删改查功能,这里要用到缓存啊 而且是mybatis这种orm框架采用缓存机制的,mybatis默认都有两层缓存了 ...

  4. Windows下IIS以FastCGI模式运行PHP

    由于PHP5.3 的改进,原有的IIS 通过isapi 方式解析PHP脚本已经不被支持,PHP从5.3.0 以后的版本开始使用微软的 fastcgi 模式,这是一个更先进的方式,运行速度更快,更稳定. ...

  5. [转载]深入理解JAVA的接口和抽象类

    深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...

  6. 在XML里的XSD和DTD以及standalone的使用3----具体使用详解

    本人亲自写的一个简单的测试例子 1.xsd定义 <?xml version="1.0" encoding="utf-8"?><xs:schem ...

  7. Linux改IP后务必重启网络服务

    [root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0BOOTPROTO=noneONBOOT=yes ...

  8. linux delete files older than 3 days

    4 down vote accepted This is easy enough (although note that this goes by a modification time more t ...

  9. Android Studio 我常用快捷键

    0. Ctrl+Alt+L 格式化代码 Ctrl+Alt+O 优化导入的类 1. 重载方法 Ctrl+O 2.Ctrl+shift+Enter:自动匹配相对应的语法结构,比如if,do-while,t ...

  10. LeetCode Contains Duplicate (判断重复元素)

    题意: 如果所给序列的元素不是唯一的,则返回true,否则false. 思路: 哈希map解决. class Solution { public: bool containsDuplicate(vec ...