Objective-C Blocks

Objective-C Blocks

All of these examples have been verified with this version of LLVM:

Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin11.4.2
Thread model: posix

Example A

void exampleA() {
  char a = ‘A‘;
  ^{
    printf("%c\n", a);
  }();
}

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.

Example B

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();
}

This only works with ARC.

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.

Example C

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();
}

This always 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.

Example D

typedef void (^dBlock)();

dBlock exampleD_getBlock() {
  char d = ‘D‘;
  return ^{
    printf("%c\n", d);
  };
}

void exampleD() {
  exampleD_getBlock()();
}

This only works with ARC.

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 E

typedef void (^eBlock)();

eBlock exampleE_getBlock() {
  char e = ‘E‘;
  void (^block)() = ^{
    printf("%c\n", e);
  };
  return block;
}

void exampleE() {
  eBlock block = exampleE_getBlock();
  block();
}

This only works with ARC.

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.

Conclusions

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.

Haha! No, of course it’s not that simple. According to Apple:

Blocks “just work” when you pass blocks up the stack in ARC mode, such as in a return. You don’t have to call Block Copy any more. You still need to use [^{} copy] when passing “down” the stack into arrayWithObjects: and other methods that do a retain.

But one of the LLVM maintainers later said:

We consider this to be a compiler bug, and it has been fixed for months in the open-source clang repository. What that means for any hypothetical future Xcode release, I cannot say. 

So, hopefully Apple was describing a workaround for bugs that existed at the time their guide was written, and everything should work smoothly with ARC and LLVM in the future. But watch out. 

But there are incoordination ideas.

"Always use ARC" feels akin to saying "don‘t bother understanding how block lifecycles actually work". Blocks work correctly without ARC, too. If you don‘t understand the difference between stack- and heap-allocated memory, you are in for trouble eventually. In these cases, ARC is just protecting you from the incorrect code, and actually kinda encouraging the poor understanding of the issue.

One real bug here shows up in examples B and C. In both examples, NSMutableArray will retain the blocks. This is a logical error, because you cannot retain stack blocks. This is an obvious and immediate bug, but instead of an exception, its a no-op.

From:http://blog.parse.com/2013/02/05/objective-c-blocks-quiz/

时间: 2024-12-17 07:41:22

Objective-C Blocks的相关文章

objective c 代码块blocks完整总结一

在ios4之后,引入了代码块的特性,在gcd中会经常的用到,所以决定好好的看看代码块文档,把这块总结一下.从头开始讲解代码块. 1.声明和使用代码块 一般用^操作符声明一个块变量,并作为块的开始符.而块的本身用{}包括起来,就像下面那样. int multiplier = 7; int (^myBlock)(int) = ^(int num) { return num * multiplier; }; int(^myblocks)(int)=(^int  num){return num * mu

objective c 代码块blocks完整总结二

1. block基础 block声明有点像c语言的函数指针 C代码 int func(int); int (*pfunc)(int); int func(int p) { printf("%d", p); return p; } 其中func是函数, pfunc是函数指针函数指针赋值  pfunc = &func;函数指针使用 (*pfunc)(100);block的声明 int (^bfunc)(int);block的赋值 bfunc = ^(int p){   printf

Windows下安装Code::Blocks 13.12进行C/C++开发

CodeBlocks 是一个开放源码的全功能的跨平台C/C++集成开发环境.CodeBlocks是开放源码软件.CodeBlocks由纯粹的C++语言开发完成,它使用 了蓍名的图形界面库wxWidgets(2.6.2unicode)版.对于追求完美的C++程序员,再也不必忍受Eclipse的缓慢,再也不必忍受 VS.NET的庞大和高昂的价格. CodeBlocks 提供了许多工程模板,这包括:控制台应用.DirectX应用.动态连接库.FLTK应用.GLFW应用.Irrlicht工程.OGRE应

[2016-03-11][POJ][1609][Tiling Up Blocks]

[2016-03-11][POJ][1609][Tiling Up Blocks] Tiling Up Blocks Time Limit: 1000MS Memory Limit: 10000KB 64bit IO Format: %I64d & %I64u Submit Status Description Michael The Kid receives an interesting game set from his grandparent as his birthday gift. I

Objective -C Categories

Objective -C Categories? The dynamic runtime dispatch mechanism employed by Objective-C lets you add methods to existing classes. 被Objective -C 采纳的动态运行分配机制让你可以在已有的类中添加方法. 1.1 Creating a Category 创建一个Category? A category is a way to add new methods to

POJ1609:Tiling Up Blocks(DP)

Description Michael The Kid receives an interesting game set from his grandparent as his birthday gift. Inside the game set box, there are n tiling blocks and each block has a form as follows: Each tiling block is associated with two parameters (l,m)

Objective - c Foundation 框架详解2

Objective - c  Foundation 框架详解2 Collection Agency Cocoa provides a number of collection classes such as NSArray and NSDictionary whose instances exist just to hold onto other objects. cocoa 提供了一系列的集合类,例如,NSarray,NSdictionary.它们存在的目的就是为了保持其他对象. 1.1.1N

Code::Blocks 使用 AStyle 格式化 C/C++ 代码

目录 AStyle Code::Blocks Source code formatter plugin Source code formatter (AStyle) shortcut AStyle A Free, Fast, and Small Automatic Formatter for C, C++, C++/CLI, Objective?C, C#, and Java Source Code Project Page: http://astyle.sourceforge.net/ Sou

【Code::Blocks】windows 环境下编译 Code::Blocks(已修正)

Code::Blocks 在2012-11-25发布了最新的12.11版本,相比上一个版本(10.05),Code::Blocks 进行了许多改进和更新(Change log). 引用 Wikipedia:Code::Blocks: Code::Blocks是一个免费.开源.跨平台的IDE,使用C++开发,并且使用wxWidgets做为GUI函式库.Code::Blocks使用了插件架构,其功能可以使用插件自由地扩充.目前, Code::Blocks主要针对开发C/C++程式而设计. Code:

Using ffmpeg libraries in Code::Blocks

I am digging into a project that needs to use some open source video codec library. ffmpeg is very powerful video codec library, which I decided to use in my project. I compiled and installed the ffmpeg library, then the problem comes, how to use the