5

当我通过 GCD 掌握多线程技术时,我遇到了一些问题。假设您有以下方法:

    - (void)method {
    NSString *string= [NSString string]; //will be autoreleased

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    //very very lengthy operation...

    NSLog(@"%@", string); //is it safe?
    });
}

我想知道这是否正确,因为我认为我应该在块执行之前保留字符串:实际上我担心事件循环完成并在块中string使用之前发送一条自动释放消息string。那会使程序崩溃。

我对吗?我应该发送保留和释放消息string还是这是正确的实现?提前致谢!

4

2 回答 2

5

我想知道这是否正确,因为我认为我应该在块执行之前保留字符串:实际上我担心事件循环完成并在块中使用字符串之前向字符串发送自动释放消息。

不要害怕:
块捕获了周围方法/函数的范围,因为它自动retain成为块内使用的任何对象变量。请注意,在self块内部使用时,这可能会极大地影响对象的生命周期!

此规则有一个例外,即声明为的变量

__block SomeObjectPointerType variableName

更新

因为这个答案有一个新的评论,我可能应该补充一点,随着 ARC 的引入,事情发生了一些变化:

在 ARC 下,所有对象变量默认为__strong这也适用于标记为的变量__block。如果你想避免在块中强捕获变量,你应该定义一个局部变量是__weak.

结束更新

如果你想了解更多关于 Block 的信息,bbum在 WWDC 2010上提供了一个名为Introducing Blocks 和 Grand Central Dispatch on iPhone的精彩会议。

“区块详情”部分从 11:30 开始。

于 2011-02-13T13:35:20.250 回答
-5

令人担忧的是;自动释放对象何时释放?

NSString *myString= [NSString stringWithFormat: @"%@", stringVariable];

myString 依赖于 stringVariable,只要 stringVariable 释放,myString 就会立即释放。

NSString *myString= [NSString stringWithString: @"stringVariable"];

在实践中,可以观察到 myString 可能会在方法完成后立即发布。

现在,如果您更改代码并使用NSAutoReleasePool

- (void)method {
    NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init];

    NSString *string= [NSString string]; //will be autoreleased

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    //very very lengthy operation...

    // string will be released here
    [pool release];

    NSLog(@"%@", string); // it is not safe?
    });
}

自动释放对象在它们所在的自动释放池释放或它们所依赖的对象释放时释放。

现在,如果您在线程中使用该方法,则应该在其中使用自动释放池。

- (void)method {
    NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init];

        // lengthy operations ...
    [pool release];
}
于 2011-02-13T11:16:28.297 回答