objective c在后台和autoreleasepool中执行选择器

时间:2012-10-15 19:39:23

标签: iphone objective-c

我正在开发一个iphone应用程序,它有一些存储在sqllite数据库中的数据。当我的视图加载时,我想在后台线程上加载数据库中的数据。问题是应用程序不断崩溃,我不知道为什么。

代码:

-(id) init
{
    if((self=[super init]))
    {
       [self performSelectorInBackground:@selector(loadList) withObject:nil];
    }
 }

-(void) loadList
{
   @autoreleasepool
   {
      Loader * loader = [[Loader alloc] init];
      NSMutableArray * array = [loader getItemList];
      [array retain];
      NSLog(@"Got %d items",[array count]);

      [self performSelectorOnMainThread:@selector(createList:) withObject:array waitUntilDone:false];
      [loader release];
   }
}

-(void) createList: (NSMutableArray*) array
{
    items = array;
    int i;
    Item * it;
    for(i = 0; i < [items count]; i++)
    {
      it = [items objectAtIndex: i];
      [it getName]; // crashes
      // populate the list
    } 
}

Loader返回带有Item对象的NSMutableArray。当我调用项getName(返回NSString *)时,应用程序崩溃。从我的理解崩溃,因为项目名称属性正在发布。我究竟做错了什么?

谢谢!

3 个答案:

答案 0 :(得分:1)

这个特殊的错误似乎是你正在传递waitUntilDone:NO,因此数组会立即被释放,因此它的项目也是如此。

但总的来说,UIKit不是线程安全的,所以这只是一个敏感的设计。我可能会将这些东西加载到另一个为您处理任务的类中而不是在视图中。

答案 1 :(得分:1)

对于您用于填充array的任何类型的对象,这可能是一个问题。

我无法找到手指纸上的证据,但我确信performSelectorOnMainThread:withObject:waitUntilDone:会保留其对象。但是,如果array中的每个项目都保留对loader的引用,那么他们需要负责保留该对象。看起来你试图手动保持它活着但是 - 正如Chuck暗示的那样 - 你对performSelector...的呼叫将立即返回,而不是等待你完成的呼叫。

答案 2 :(得分:0)

我在这一行上放了一个断点:

 it = [items objectAtIndex: i];

然后输入

po it
在调试器中

,看看名称字段中有什么。作为一个猜测,我会说两件事之一:1)getName返回的字段没有用对象初始化(即不是真正的NSString *)或者你从SQLite获得一个C字符串(其中)它通常会返回)并且您正试图将其视为NSString *。如果是后者,您可以使用[myCString stringWithUTF8String]将C字符串转换为NSString *