can anyone tell flow of execution of blocks in objective c? [closed]

假装没事ソ 提交于 2019-12-23 06:23:10

问题


Hi iam working with Blocks in objective-c. I have just learn syntax, and how to write blocks. But i didn't understand execution flow. I googled it for flow of execution, i can't find.

I used the following code :

@interface NSArray (Extended)
- (NSArray *)each:(void (^)(id))block;
@end

@implementation NSArray (Extended)
- (NSArray *)each:(void (^)(id object))block {
for(id mObject in self)
    block(mObject);
return self;
}
@end

int main (int argc, const char * argv[]) {
@autoreleasepool {

  NSArray *array = [NSArray arrayWithObjects:@"Number one", @"Number two", nil];
  [array each:^(id object) {
     NSLog(@"obj: %@", object);
  }];

}
return 0;
}

Can anyone explain what is the flow of execution of blocks in objective-c?


回答1:


Not sure how you want to explain the thing. Here is my attempt:

Block is a piece of code. When you create a block using ^{}, that code can be stored in variable. In your case (and in most of the cases) it is immediatelly passed to method as argument, just like any other value. This example block declares 1 argument, whose value must be specified when the code will be executed. Variable object_in will contain some object and you can work with it in the block of code.

[array each:^(id object_in) {
    NSLog(@"object: %@", object_in);
}];

Inside of the method, the code is stored in argument variable, named block in your case. Now you want to execute the code. You do it by appending parentesis with the list of real values as block arguments. Now object_out contains some real value and so it will be passed to object_in.

- (NSArray *)each:(void (^)(id))block {
    for (id object_out in self) {
        block(object_out); // executes the code of block with given argument
    }
    return self;
}

Now your NSLog statement is executed with every object in the array.

It is very similar to function pointer. If you know something about it, is may be easier, if not, don't bother with that :)


So you can pass values to block by arguments, but there is also second way to get values into block. It is about capturing local variables, but it is not used in your example. If you or anyone else wanted me to explain it, feel free to comment.


Edit: So here is light explanation for captured variables. Every piece of code enclosed in {} is scope and so block is also a scope. Scopes are nested and local variables created in them are valid only until the control flow leaves the scope. Child scopes can use variables from parent scope.

Example code below iterates two arrays, one by for-in loop and second by -each: method from the question. The block passed as argument is now slightly different – it uses one variable from the parent scope (in fact it's from grandparent scope). Why is this block different? The method -each: will be executed multiple times, every time with string containing different value. In another words, 3 instances of the block will be created each with its' own string value.

NSArray *strings = @[ @"A", @"B", @"C" ];
NSArray *numbers = @[ @1, @2, @3 ];

NSString *string = nil; // doing this to be more obvious
for (string in strings) {
    // string is simple local variable
    [numbers each:^(id number) {
        // number is argument
        NSLog(@"argument: %@, captured: %@", number, string);
    }];
}

Output:

argument: 1, captured: A
argument: 2, captured: A
argument: 3, captured: A
argument: 1, captured: B
argument: 2, captured: B
argument: 3, captured: B
argument: 1, captured: C
argument: 2, captured: C
argument: 3, captured: C

So we have code, that is common to all 3 instances and some variable that is (can be) different for each of them. If this reminds you of class / object relationship, you are right.

Argument is different for each invocation of the block (shown in previous code examples) and captured variables are different for each instance. New instance is created every time the line with block definition (^{) is executed.




回答2:


Sure.

  • main() is called

  • an array is allocated containing two strings

  • the each: method is invoked on the array, passing a block that takes a single object as an argument

  • the each: method iterates over all objects in the array using a for() loop

    • the block passed to the each: method is called once for each object, with the object being the argument to the block

    • the block logs a line describing the object


A block captures code at compile time and state at runtime. In this case, the block isn't capturing any state. The block is just like a simple C function that just prints one log line every time it is called.




回答3:


From Documentation:

Block objects are a C-level syntactic and runtime feature. They are similar to standard C functions, but in addition to executable code they may also contain variable bindings to automatic (stack) or managed (heap) memory. A block can therefore maintain a set of state (data) that it can use to impact behavior when executed.

For futher clarification check this link.



来源:https://stackoverflow.com/questions/16355684/can-anyone-tell-flow-of-execution-of-blocks-in-objective-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!