Objective-C blocks

Source: Internet
Author: User
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.2Thread model: posix
Example
void exampleA() {  char a = ‘A‘;  ^{    printf("%c\n", a);  }();}

This always works. The stackexampleADoesn'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 isNSStackBlockAllocated on the stackexampleB_addBlockToArray. By the time it executes inexampleB, The block is no longer valid, because that stack has been cleared.

With arc, the block is properly allocated on the heap as an autoreleasedNSMallocBlockTo begin.

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 asNSGlobalBlock. 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 wocould be created on the stackexampleD_getBlockAnd 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 errorerror: returning block that lives on the local stack.

With arc, the block is correctly placed on the heap as an autoreleasedNSMallocBlock.

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, doesn t that the compiler doesn't recognize it as an error, so this Code compiles and crashes. even worse, this maid 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 autoreleasedNSMallocBlock.

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 defensivelyblock = [[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 asNSMallocBlock.

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 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 xcode ure 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 shocould 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/

Objective-C blocks

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.