美文网首页
block的整理

block的整理

作者: YuWenHaiBo | 来源:发表于2016-08-09 17:05 被阅读70次
  • 先看看第一道题:

Example A

void exampleA() { char a = 'A'; ^{ printf("%cn", a); }();}

This example

  • <u>always works.</u>
  • only works with ARC.
  • only works without ARC.
  • never works.

This always works. The stack for exampleA doesn't go away until after the block has finished executing. So whether the block is allocated on the stack or the heap, it will be valid when it is executed.
正确答案是,不管是ARC还是非ARC的环境下都能运行,这个exampleA 的栈没有释放,直到这个block执行完毕,因此这个block不管是分配到栈区还是堆区,它将不会失效,直到被执行。

  • 接下来第二道

Example B

 void exampleB_addBlockToArray(NSMutableArray * array)  {
         char b = 'B'; 
         [array addObject:^{
          printf("%cn", b); 
       }];
}
// 
 void exampleB()  { 
          NSMutableArray * array = [NSMutableArray array]; 
          exampleB_addBlockToArray(array);
          void (^block)() = [array objectAtIndex:0];
          block();
}
  • This example
  • always works.
  • <u>only works with ARC. </u>
  • only works without ARC.
  • never works.

Without ARC, the block is an NSStackBlock allocated on the stack of exampleB_addBlockToArray. By the time it executes in exampleB, the the block is no longer valid,because that stack has been cleared. With ARC, the block is properly allocated on the heap as an autoreleased NSMallocBlock to begin with.
非ARC(MRC)模式下,exampleB_addBlockToArray函数中的block被分配在NSStackBlock中,这个block不会长时间有效,因为这个栈已经被清空了(函数返回就清空),在ARC中这个block几乎是分配在NSMallocBlock堆中(引用计数器为0开始销毁)

Example C

void exampleC_addBlockToArray(NSMutableArray *array)  {
 [array addObject:^{
   printf("Cn"); 
  }];
}
void exampleC() { 
  NSMutableArray *array = [NSMutableArray array]; 
  exampleC_addBlockToArray(array);
  void (^block)() = [array objectAtIndex:0]; 
  block();
}
  • This example
  • <u>always works.</u>
  • only works with ARC.
  • only works without ARC.
  • never works.

Since the block doesn't capture any variables in its closure, it doesn't need any state set up at runtime. it gets compiled as an NSGlobalBlock
. It's neither on the stack nor the heap, but part of the code segment, like any C function. This works both with and without ARC.
自从这个block没有获取一些变量在它的闭包,它不需要设置一些状态在运行时中。它开始编译的时候,被当做NSGlobalBlock。这个block不属于堆和栈,但是一部分在代码区中,比如一些C函数。这个可以在ARC和MRC中执行。

Example D

typedef void (^dBlock)();
  dBlock exampleD_getBlock() { 
  char d = 'D'; 
  return ^{ 
    printf("%cn", d);
 };
}
void exampleD() { 
  exampleD_getBlock()();
}
  • This example
  • always works.
  • <u>only works with ARC.</u>
  • only works without ARC.
  • never works.

This is similar to example B.
Without ARC, the block would be created on the stack of exampleD_getBlock and then immediately become invalid when that function returns. However, in this case, the error is so obvious that the compiler will fail to compile, with the error error: returning block that lives on the local stack.
With ARC, the block is correctly placed on the heap as an autoreleased NSMallocBlock.
** 这个和example B 相似,在MRC中,exampleD_getBlock中block将会被创建在栈中,当函数返回的时候立即就被释放了。然而,在这个情况下,这是个很明显的错误,这个编译将会失败,报returning block that lives on the local stack.
在ARC中,这个block是没问题的,exampleD_getBlock中block将会被创建在NSMallocBlock 堆中**

Example E

typedef void (^eBlock)();
eBlock exampleE_getBlock() { 
  char e = 'E';
   void (^block)() = ^{ printf("%cn", e);
 };
   return block;
}
void exampleE() {
   eBlock block = exampleE_getBlock(); 
   block();
}
  • This example

  • always works.

  • <u>only works with ARC.</u>

  • only works without ARC.

  • never works.

This is just like example D, except that the compiler doesn't recognize it as an error, so this code compiles and crashes. Even worse, this particular example happens to work fine if you disable optimizations. So watch out for this working while testing and failing in production.
With ARC, the block is correctly placed on the heap as an autoreleased NSMallocBlock.
这个和example D相似,除开编译的时候不会报错,运行会崩溃这个error,更糟糕的是,这个实际的例子正常运行如果你不优化,因此使用的时候注意了
在ARC时候,这个block是正确的申请在NSMallocBlock堆中的

总结:

So, what's the point of all this? The point is always use ARC. With ARC, blocks pretty much always work correctly. If you're not using ARC, you better defensively block = [[block copy] autorelease]
any time a block outlives the stack frame where it is declared. That will force it to be copied to the heap as an NSMallocBlock.
** 因此,这些表明了,我们尽量使用ARC,在ARC中block更多情况下是正确的,如果你是不用ARC你就得这样写block block = [[block copy] autorelease]任何的时候,一个block将要离开声明的作用域的时候,就会强制它copy一次,将block拷贝到NSMallocBlock中 **

个人总结:

  • 在 Objective-C 语言中,一共有 3 种类型的 block:
  • _NSConcreteGlobalBlock 全局的静态 block,不会访问任何外部变量。
  • _NSConcreteStackBlock 保存在栈中的 block,当函数返回时会被销毁。
  • _NSConcreteMallocBlock 保存在堆中的 block,当引用计数为 0 时会被销毁。
  • 在 ARC 开启的情况下,将只会有 NSConcreteGlobalBlock 和 NSConcreteMallocBlock 类型的 block。

相关文章

  • block的整理

    先看看第一道题: Example A This example always works. only works ...

  • Block的整理

    使用Block在两个界面之间传值 1. 在 B 控制器的.h文件中定义声明Block属性 typedef void...

  • Block整理

    Block 概念 闭包 = 一个函数「或指向函数的指针」+ 该函数执行的外部的上下文变量「也就是自由变量」;Blo...

  • 整理Block

    用了Block那么久,一直以来没有好好整理,只知道如何使用,对有些概念也不是了解特别清楚,感觉似懂非懂的。借助网上...

  • Block整理

    Block block其实就是一个代码块,把你想要执行的代码封装在这个代码块里,等到需要的时候再去调用。那bloc...

  • block-整理中

    block-整理中

  • 2018.07.01

    看不进去书的时候就整理房间 一个block 一个block 的整理 从书架开始

  • Block知识整理

    2018-10-26 编辑 :yzl 1. block定义 用Apple文档的话来说,A block is an...

  • Block常用整理

    善用block,可以进行很好的封装,但总是容易混,所以整理一下~ 独立block格式: typedef 返回值类型...

  • 深入理解Objective-C的Block

    对Block的内存使用相关的内容简要整理,解释其中的道理和使用Block需要注意的问题。 1. Block与对...

网友评论

      本文标题:block的整理

      本文链接:https://www.haomeiwen.com/subject/amrdsttx.html