[tableView reloadData];在我滚动tableView之前不起作用。

21

我有一个简单的应用程序,当用户在UISearchBar中输入内容时,会下载XML格式的搜索结果。下载和解析是在线程中进行的,一旦完成,它就会触发一个NSNotification来告知带有表视图的ViewController使用[tableView reloadData];刷新数据。

下面是接收到结果后触发通知的代码:

- (void)receivedResults:(id)notification {
    results = [notification object];
    DLog(@"Received %i results",[results count]);
    [[self tableView] reloadData];
}

我收到了日志输出“接收到 4 个结果”,但是表视图直到我滚动/拖动几个像素后才重新加载数据。我正在使用内置的UITableViewCellStyleSubtitle单元格样式,并且没有改变表视图的高度或进行任何特别操作。

我做错了什么?


结果当然是一个实例变量,也是表格视图的数据源,否则即使在搜索后拖动表格视图,以上代码也无法正常工作。 - Maciej Swic
你确定 [self tableView] 不会返回 nil 吗?这可能是 reload 方法不起作用的原因,但 cellForRowAtIndexPath 方法却可以。该方法由委托调用。 - Mats Stijlaart
5个回答

66

我成功地得到了相同的结果。但问题在于刷新数据需要在主线程上调用。

dispatch_async(dispatch_get_main_queue(), ^{
    [self.tableView reloadData];
});

我认为这比使用performSelectorOnMainThread选项更实用。


不知道是否更实用,但是苹果公司建议使用GCD来代替performSelector...模式。 - Maciej Swic
@MaciejSwic 这应该是针对此特定问题的正确解决方案。问题在于 OP 正试图在后台线程上更改 UI,很可能他忘记退出了该线程。你不应该仅仅调用 performSelectorOnMainThread 以作为一种解决方法。 - JRam13
这对我没有解决问题。我的问题非常相似,但是有一个变化,即单元格仅在完全滚动出视图并重新进入视图时才显示其内容。到目前为止,我对此完全感到困惑... :-( - Erik van der Neut
@ErikvanderNeut 你好,你解决了这个问题吗?我也面临着同样的问题。 - Manimaran
嗨@Manimaran--我从未找到解决根本问题的适当方法,但是通过一个hack,我能够让它看起来好像没有问题。一旦这似乎足够健壮,我就把它留在那里了。我的hack是在显示视图之前将表格来回滚动。现在对细节有点模糊,但基本上我只是在代码中实现了一个即时来回滚动,以确保单元格已完全滚出视图并重新进入视图,然后再在屏幕上显示它。听起来很荒谬,但那个丑陋的hack确实解决了问题:-/非常奇怪... - Erik van der Neut

34

调用

[self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];

而不是

[self.tableview reloadData]

不错,我正在一个NSNotification的事件处理程序中重新加载我的数据。 - NMunro

4

我的问题在于我正在后台线程中发布一个NSNotification。为了避免这种情况,只需像这样将您的postNotificationMethod包装在dispatch_async方法中:

dispatch_async(dispatch_get_main_queue(), ^{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"FinishedDownloading" object:result];
});

当收到此通知时,tableView.reloadData将在主线程上被调用。


0

我有同样的问题,我尝试了所有在谷歌上能找到的解决方案。但是它们都不起作用。

最后我发现,在viewDidLoad之前添加观察者,然后[self.tableView reloadData]就无法工作。

首先,我在我的根导航视图控制器的viewDidLoad中调用了setObserverForUserInfoDatabase。因为我认为它被提前调用了。这个函数像这样:

- (void)setObserverForUserInfoDatabase:(NSString *)name {
    [[NSNotificationCenter defaultCenter] addObserverForName:name
                                                      object:nil
                                                       queue:nil
                                                  usingBlock:^(NSNotification *note) {
                                                      [self loadUserInfo];
                                                      [self.tableView reloadData];
                                                      NSLog(@"User Panel Notification \n %@", self);
                                                  }];}

然后我将代码移动到视图控制器本身的viewDidLoad中。

- (void)viewDidLoad {
    NSLog(@"View Did Load");
    [super viewDidLoad];

    [self setObserverForUserInfoDatabase:UserInfoDataBaseAvailabilityNotification];
}

然后一切都正常工作。

我还不知道原因。如果有人知道,请告诉我。


setObserverForUserInfoDatabase是做什么的?它之前在哪里? - Maciej Swic
这个函数只是添加观察者。我把它放在RootViewController的ViewDidLoad中,但它没有起作用。 - wgr

0
viewWillLayoutSubviews 中重新加载你的 tableView

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接