【问题标题】:Deallocating object while in background thread在后台线程中释放对象
【发布时间】:2012-01-31 03:59:37
【问题描述】:

我一直在做 iOS 项目,它在后台使用数据下载。好吧,老实说 - 实现不是最好的(后来被更改以删除这种不明显的模式),而且我在未释放对象方面遇到了一些问题,并且不能说,文档给了我一个清晰的理解发生了什么。代码,展示共同思想:

- (void)loadModelAtIndex:(NSUInteger)index {
    Model *model = [self modelAtIndex:index];
    if (model) {
        model.index = index;
        [self performSelectorInBackgroundThread:@selector(loadModelInBackgroundThread) withObject:model]
    }
}

- (void)loadModelInBackgroundThread:(Model *)model {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    model.data = [NSData dataWithContentsOfURL:model.url];
    //and some other changes can be here
    [self performSelectorOnMainThread:@selector(modelDidLoad) withObject:model waitUntilDone:NO]'
    [pool drain];
}

- (void)modelDidLoad:(Model *)model {
    [self saveModel:model atIndex:model.index];
    [self loadModelAtIndex:model.index + 1];
}

嗯,几乎所有时间它都按预期工作。除非调用者在后台下载时被释放 - 模型对象留在内存中,没有被释放(此时我的内存正在增长)。

谁能解释一下,在后台线程运行时释放的情况会发生什么?我不确定这段代码是否合适,但仍然感兴趣。任何修改都会让事情运行良好?

【问题讨论】:

    标签: objective-c ios multithreading dealloc


    【解决方案1】:

    除非调用者在后台下载时被释放 - 模型对象留在内存中

    performSelector | …Thread… 调用保留它们的参数。如果您的对象在那个时候被释放,问题就出在其他地方。在启用僵尸的情况下运行以找到它 - 您可以记录每个引用计数。

    【讨论】:

    • 因为释放对象的最后一段代码是内部线程管理本身,我们可能还需要暂时注释掉performSelectorInBackground这一行,以便能够检测到过度释放。
    • @tia Instruments 为您记录每个引用计数操作(如果需要),并带有回溯。这对于大多数用途来说已经足够了。我看到的唯一真正的问题是确保调用者从主线程中释放,如果它持有 UIKit 引用(或 something 必须在主线程上运行)。然而,这是一个单独的问题 - OP 处理僵尸:“在后台下载时调用者已被释放”
    猜你喜欢
    • 2012-03-06
    • 2016-08-31
    • 2011-09-15
    • 2020-09-10
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多