Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I don't know what patterns of block I should avoid for the literal scope in objective-c

It is said in apple's documents: A block literal (that is, ^{ ... }) is the address of a stack-local data structure that represents the block. The scope of the stack-local data structure is therefore the enclosing compound statement, so you should avoid the patterns shown in the following examples:

void dontDoThis() {

    void (^blockArray[3])(void);  // an array of 3 block references

    for (int i = 0; i < 3; ++i) {

        blockArray[i] = ^{ printf("hello, %d\n", i); };

        // WRONG: The block literal scope is the "for" loop.
    }

    //for example I invoke the block here
    blockArray[1]();
  }


void dontDoThisEither() {

    void (^block)(void);

    int i = random():

    if (i > 1000) {

        block = ^{ printf("got i at: %d\n", i); };

        // WRONG: The block literal scope is the "then" clause.

    }

    // ...

  }

I don't know what patterns I should avoid. It seems like that I could invoke the block at which has the same literal scope as the block definition, for example behind the "if" or "for" statement. Could you please help me to explain it?

Here it is the link https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Blocks/Articles/bxUsing.html#//apple_ref/doc/uid/TP40007502-CH5-SW1

like image 983
jerrylei Avatar asked Nov 27 '12 23:11

jerrylei


People also ask

What is a block in Objective-C?

Blocks are a language-level feature added to C, Objective-C and C++, which allow you to create distinct segments of code that can be passed around to methods or functions as if they were values. Blocks are Objective-C objects, which means they can be added to collections like NSArray or NSDictionary .


Video Answer


1 Answers

I think an analogy to pointers is as following.

void foo() {
  int *block = NULL;
  {
    int a;
    block = &a;
  }
  // `block`, even though defined here, points to
  // an invalid memory address.
}

Generally, the block literal itself only exists in the block it is defined in, so when leaving that block, the literal disappears (like the variable a did in the example above), and you're left with a dangling pointer.

For this reason, blocks are usually copied into the heap for future use. Non-ARC code uses block_copy and friends. Copying into the heap also captures all relevant variables your block uses (which might create retain-cycles).

In practice, all of this is quite shunned away by the use of ARC, properties and classes. You define a copy property in your class, and then just assign blocks to it. If you let the compiler generate the getter/setter, your block literal will automatically be copied into the heap.

@interface Bla : NSObject
@property (nonatomic, copy) void (^blockProperty)(int i);
@endf

...

Bla *bla = [[Bla alloc] init];
{
  bla.blockProperty = ^(int i) { printf("%d", i); };
}
// bla.blockProperty now points to a heap copy of the block literal from above,
// so it's not dangling.
like image 185
user1071136 Avatar answered Nov 10 '22 01:11

user1071136