0

我正在开发一个 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*)时,应用程序崩溃。据我了解,它崩溃是因为项目名称属性正在被释放。我究竟做错了什么?

谢谢!

4

3 回答 3

1

您用于填充的任何类型的对象都可能存在问题array

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

于 2012-10-15T21:31:15.123 回答
1

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

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

于 2012-10-15T19:50:54.760 回答
0

我会在行上放一个断点:

 it = [items objectAtIndex: i];

然后输入

po it

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

于 2012-10-15T21:08:47.953 回答