问题
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 stringsthe
each:
method is invoked on the array, passing a block that takes a single object as an argumentthe
each:
method iterates over all objects in the array using afor()
loopthe block passed to the
each:
method is called once for each object, with the object being the argument to the blockthe 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