保留在NSThread中创建的对象

时间:2009-08-04 02:37:11

标签: objective-c cocoa multithreading memory-management thread-safety

我有以下方法,它是通过调用新线程(使用NSThread)产生的:

- (void) updateFMLs {   
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSArray *temp = [[NSArray alloc] initWithArray:someArrayFromAnotherProcess];

    [self performSelectorOnMainThread:@selector(doneLoading:) withObject:temp waitUntilDone:NO];
    [pool release];
}

我的doneLoading:方法如下所示:

- (void) doneLoading:(NSArray *)obj {
    myArray = [[NSArray alloc] initWithArray:obj copyItems:NO];
}

myArray的内容无效。如何保留myArray的内容,以便稍后在我的应用中使用它们?

P.S。 myArray在类头文件中定义。

3 个答案:

答案 0 :(得分:1)

如果你的后台线程做了一些工作并且需要将NSArray“传递”到你的主线程,那么所有doneLoading需要做的是:

-(void)doneLoading:(NSArray *)obj
{
    [myArray release]; // release the previous array and its objects
    myArray = [obj retain];
    // now use myArray, refresh tables, etc.
}

(可能)不需要制作阵列的另一个副本,这可能是潜在的问题。您应该在[temp release]电话后致电performSelector,因为已经保留了对此的论据。

如果myArray的内容以某种方式变得有效,那么它们会在某处被双重释放。 myArray将保留添加到其中的所有对象。您提到myArray本身变得无效,因此请尝试使用此模式重写后台线程和doneLoading方法。

最后,您应该使用[pool drain]代替[pool release]

答案 1 :(得分:0)

除了updateFMLs中的内存泄漏之外,您发布的代码看起来很好。您可能在其他地方过度释放对象。我猜这将是someArrayFromAnotherProcess的所在地。

答案 2 :(得分:0)

上述选项的替代方法是将myArray声明为标题

中的原子属性
@property (atomic,retain) NSArray *myArray;

然后在updateFML中你应该能够简单地从辅助线程调用setter。显然,只有当你愿意支付原子属性的性能损失时,这才有效。

- (void) updateFMLs {
    NSAutoreleasePool *pool - [[NSAutoreleasePool alloc] init];
    NSArray *temp = [[NSArray alloc] initWithArray:someArrayFromAnotherProcess];
    [self setMyArray:temp];
    [temp release];
    [pool drain];
}