我喜欢在objective-c中使用Blocks。我刚学习语法,以及如何编写块。但我不明白执行流程。我用Google搜索了执行流程,我找不到。
我使用了以下代码:
@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;
}
任何人都可以解释objective-c中块的执行流程是什么?
答案 0 :(得分:5)
不确定
main()被称为
分配了array
,其中包含两个字符串
在数组上调用each:
方法,传递一个以单个对象为参数的块
each:
方法使用for()
循环遍历数组中的所有对象
传递给each:
方法的块对每个对象调用一次,对象是块的参数
该块记录描述对象的行
块在编译时捕获代码,在运行时捕获状态。在这种情况下,块不捕获任何状态。该块就像一个简单的C函数,每次调用它时只打印一条日志行。
答案 1 :(得分:3)
不确定你想如何解释这件事。这是我的尝试:
Block是一段代码。使用^{}
创建块时,该代码可以存储在变量中。在您的情况下(在大多数情况下),它立即作为参数传递给方法,就像任何其他值一样。此示例块声明了1个参数,当执行代码时,必须指定其值 。变量object_in
将包含一些对象,您可以在代码块中使用它。
[array each:^(id object_in) {
NSLog(@"object: %@", object_in);
}];
在方法内部,代码存储在参数变量中,在您的案例中名为block
。现在您要执行代码。您可以通过使用实际值列表作为块参数附加parentesis来实现。现在object_out
包含一些实际值,因此会传递给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;
}
现在,您的NSLog
语句将与数组中的每个对象一起执行。
它与函数指针非常相似。如果您对此有所了解,可能会更容易,如果没有,请不要理会:)
所以你可以通过参数传递值到块,但是还有第二种方法可以将值传递给块。它是关于捕获局部变量,但在您的示例中不使用它。如果您或其他任何人想让我解释,请随时发表评论。
编辑:以下是捕获变量的简要说明。 {}
中包含的每段代码都是范围,因此块也是范围。范围是嵌套的,并且在其中创建的局部变量仅在控制流离开范围之前有效。子范围可以使用父范围中的变量。
下面的示例代码在问题中迭代两个数组,一个是for-in
循环,另一个是-each:
方法。作为参数传递的块现在略有不同 - 它使用来自父作用域的一个变量(实际上它来自祖父作用域)。为什么这个块不同?方法-each:
将多次执行,每次string
包含不同的值。换句话说,将使用“自己的string
值创建块的3个实例。
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);
}];
}
输出:
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
所以我们有代码,这对所有3个实例都是通用的,并且每个实例都有一些不同的变量(可能)。如果这会让你想起类/对象关系,那么你是对的。
每次调用块时的参数都不同(在前面的代码示例中显示),并且捕获的变量对于每个实例都是不同的。每次执行具有块定义(^{
)的行时,都会创建新实例。
答案 2 :(得分:1)
来自文档:
块对象是C级语法和运行时功能。它们类似于标准C函数,但除了可执行代码之外,它们还可能包含对自动(堆栈)或托管(堆)内存的变量绑定。因此,块可以维护一组状态(数据),以便在执行时可以用来影响行为。
如需进一步说明,请查看link。