我有一个IOS项目(禁用ARC),它有几个视图控制器。一个特定的控制器初始化MyClass类型的成员对象,但是当视图控制器被解除时,我正在为使用线程(使用dispatch-async)的对象调用一个清理方法来进行一些耗时的操作然后在这些操作时我在对象的主队列上执行[self release]。这是一个很好的做法,会导致任何错误吗?以下是与我正在做的类似的例子:
@implementation ViewController
- (void)viewDidLoad
{
myObj = [[MyClass alloc] init];
}
-(void)viewWillDisappear
{
[myObj cleanup];
}
@end
//myClass
@implementation MyClass
- (void)cleanup()
{
dispatch_queue_t myQueue = dispatch_queue_create ("MyClassDeallocQueue", NULL);
dispatch_async(myQueue, ^{
//time consuming operations
dispatch_async(dispatch_get_main_queue(), ^{
[self release];
});
});
}
@end
答案 0 :(得分:0)
这是一个好习惯吗,会导致任何错误吗?
目前,您的代码具有不平衡的保留/释放。这绝对是一个错误(过度释放)。
“这是好的做法吗?” - 好吧,我不知道你想要完成什么。但是如果你的目标是让self
保持活着,那么在块被执行之后,它已经完全通过将被捕获self
的事实完成。因此,严格来说不需要release
。
但是,如果您没有在主线程上明确释放self
,则会引入一个微妙的错误:该块可能会出现 last 对self
的引用,并且因为它可以在某个任意线程上执行,所以它将在这个非主线程上释放self
。这是禁止的:必须在主线程上调用UIKit方法(包括dealloc)!
因此,它可能有意义:
[self retain];
dispatch_async(myQueue, ^{
// time consuming operation, which captures `self`
[self doSomething];
...
// ensure that `dealloc` will be executed on the main thread, if
// last reference is held by the block:
dispatch_async(dispatch_get_main_queue(), ^{
[self release];
});
});
或更短:
dispatch_async(myQueue, ^{
// time consuming operation, which captures `self`
[self doSomething];
...
// ensure that `dealloc` will be executed on the main thread, if
// last reference is held by the block:
dispatch_async(dispatch_get_main_queue(), ^{
[self self];
});
});
修改强>
这是一个有趣的问题,“短”版本是否实际上是踩踏板的还是有种族:
假设,self
将在 myQueue 上执行的块中发布,因为在之前捕获self
的效果将是保留在同一块中,作为捕获self
对主队列上执行的块的效果。然后,我们有一个问题。评论赞赏。