当我通过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?
});
}
我想知道这是否正确,因为我认为我应该在块执行之前保留字符串:实际上我担心事件循环结束并在使用{{1}之前发送string
自动释放消息在块中。这会使程序崩溃。
我是对的吗?我应该向string
发送保留和发布消息,还是这是正确的实现?
提前谢谢!
答案 0 :(得分:5)
我想知道这是否正确,因为我认为我应该在块执行之前保留字符串:实际上我担心事件循环结束并在块中使用字符串之前发送字符串自动释放消息。 / p>
不要害怕:
块捕获周围方法/函数的范围,因为它自动retain
在块内部使用的任何对象变量。在块中使用self
时要注意这一点,因为这可能会极大地影响对象的生命周期!
此规则有一个例外,即声明为
的变量__block SomeObjectPointerType variableName
因为对这个答案有新的评论,我应该补充说,随着ARC的引入,情况发生了一些变化:
在ARC下,所有对象变量默认为__strong
,而也适用于标有__block
的变量。如果要避免在块中强烈捕获变量,则应定义__weak
的局部变量。
如果您想了解更多有关积木的信息,bbum会在WWDC 2010上举办了一场名为 Introducing Blocks and Grand Central Dispatch on iPhone (iTunes U链接)的精彩会议。
"阻止细节"部分从11:30开始。
答案 1 :(得分:-5)
关注点是;什么时候自动释放对象发布?
NSString *myString= [NSString stringWithFormat: @"%@", stringVariable];
每当stringVariable释放myString时,myString都依赖于stringVariable。
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];
}