谁能告诉客观c中块的执行流程?

时间:2013-05-03 09:29:40

标签: objective-c objective-c-blocks

我喜欢在objective-c中使用B​​locks。我刚学习语法,以及如何编写块。但我不明白执行流程。我用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中块的执行流程是什么?

3 个答案:

答案 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