2012-11-07 39 views
0

我有一个UITableView的问题。我在后台线程中从数据库服务器加载数据,如果完成,它会发送通知。在通知中,我更新了我的视图的数据数组,并在tableview上使用reloadData。 然后tableview取消选择所选的行(这意味着数据被重新加载),如果我想选择另一行,我会在didSelectRowAtIndexPath的第一行获得EXC_BAD_ACCESS,即使它只是一个NSLog。重新加载数据后选择行崩溃

如果我不分配新数组,后台线程会将变量数据提供给我并且不使用reloadData我没有使用didSelectRowAtIndexPath的问题,但tableview不显示最近的记录。用户必须关闭视图并再次打开以查看更改。这真的很糟糕,我想在后台线程完成从服务器加载记录后马上显示这些更改。

在.h文件中声明的变量:

-downloadThread是NSThread,

- 数据是一个NSArray,

-manager是我的SQL接口。

-(void)viewDidLoad 
{ 
    ... 
    [super viewDidLoad]; 
    NSMutableArray *arr = [[manager getTeilnehmerList] retain]; 
    data = arr; 
    [self.tableView reloadData]; 

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(KundenUpdated:) name:@"ContactUpdate" object:nil]; // to be notified when updating thread is finished 

downloadThread = [[NSThread alloc] initWithTarget:self selector:@selector(teilnehmerLoad:) object:nil]; //Thread to get actual data on Background 
[downloadThread performSelector:@selector(start) withObject:nil afterDelay:2]; 
    ... 
} 

-(void)teilnehmerLoad:(id)sender 
{ 
    [manager loadTeilnehmerFromServerAndInsertIntoDatabase]; 
    //data = [manager getTeilnehmerList]; 
    [self.tableView reloadData]; 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ContactUpdate" object:nil]; 

} 
-(void)KundenUpdated:(NSNotification*)notifaction 
{ 
    @synchronized(self) 
    { 
     //needs function to select row that was selected before reload if the data record is still there after sync with server 
     [self.tableView reloadData]; 
     NSLog(@"count data in kundenupdated: %i",data.count); 
    } 
} 
+0

请在通知方法中发布代码? –

+0

那么你在didSelectRowAtIndexPath的第一行记录什么?在cellForRowAtIndexPath中发生了什么?我怀疑这是你的错误所在,可能无法正确回收细胞。 –

+0

请注意,您不应该从后台调用reloadData(这肯定会导致崩溃),但应该使用peformSelectorOnMainThread或其他方法来使调用在UI线程中执行。 –

回答

0

我怀疑teilnehmerLoad被称为在你的后台线程,它的调用reloadData,这是一个禁忌。

更改它(和/或KundenUpdated)以使用performSelectorOnMainThread来执行reloadData。

确保您没有从后台线程中执行任何其他UI操作。

+0

在后台线程我开始teilnehmerload:如果它完成它发送通知“ContactUpdate”和视图已添加本身作为此通知的观察员,并应启动kundenUpdated:然后。是kundenUpdated:仍然在后台线程?我认为这是在MainThread上,这就是为什么假设我可以重新加载数据。如果我使用performSelectorOnMainThread,我应该如何构建它?我写了[self performSelectorOnMainThread:(KundenUpdated)withObject:nil waitUntilDone:YES];在teilnehmerLoad:现在但我得到一个编译器错误“使用未声明的标识符'KundenUpdated'” – Wenduros

+0

确定最后一个问题是我的错误阅读快速;)我忘了@选择器(kundenUpdated :) – Wenduros

+0

@Wenduros - 我在这个话题上有点弱,但我认为,默认情况下,通知在通知线程中运行。然而,IIRC有一种方法可以指导它在不同的线程上运行。 –