【问题标题】:when is the right time to reloadData什么时候重新加载数据合适
【发布时间】:2010-10-31 02:11:18
【问题描述】:

我有一个 DetailsViewController 类和一个 ItemsViewController 类。 (均源自 UITableViewController)

选择 ItemsViewController 中的任何项目都会打开 DetailsViewController。为了让它显示除第一个以外的任何新数据,我目前有

- (void)viewWillAppear:(BOOL)动画 { [超级viewWillAppear:动画]; [[self navigationItem] setTitle:title]; [[self tableView] reloadData]; }

工作,但感觉就像用大锤杀死苍蝇。有什么更好的方法来做到这一点?

提前致谢,

艾伦

【问题讨论】:

  • 上面这段代码是从哪里来的? ItemsView 或 DetailsView...你说它们都是表。
  • 对不起,我应该提到的。这是来自详细信息视图。

标签: iphone objective-c


【解决方案1】:

在这里结合几个 cmet 的想法:

添加

BOOL needReload
作为详细信息控制器的成员变量。

然后在细节控制器中:

- (void)setData:(DataClass *)value { 如果(值 == 数据) 返回; id 指针 = 数据; 数据 = [价值保留]; [指针释放]; // 保留后释放 需要重新加载 = TRUE; } - (void)viewWillAppear:(BOOL)动画 { [超级viewWillAppear:动画]; 如果(需要重新加载){ [[self navigationItem] setTitle:title]; [[self tableView] reloadData]; 需要重新加载 = FALSE; } }

【讨论】:

    【解决方案2】:

    如果您知道只有特定的行或部分会发生变化,您可以指示烘焙视图仅重新加载那些行或部分。除此之外,-reloadData 是大多数表格视图的选择。

    【讨论】:

      【解决方案3】:

      我假设明细表上的项目会根据项目表上的选定项目而变化。所以,是的,这应该没问题。

      除此之外,您可以检查上次是否选择了相同的项目,并且在这种情况下不调用 reloadData。

      【讨论】:

        【解决方案4】:

        艾伦,

        您关于“为了让它显示除第一个之外的任何数据的新数据”的声明让我很担心 - 因为它告诉我您可能只有一个 DetailsViewController 实例。

        在您的第一个表视图 ItemsViewController 中,您可能有一个 didSelectRowAtIndexPath: 方法用于将 DetailsViewController 推入 UINavigationController 堆栈。

        我解决此问题的方法是在每次用户在视图之间点击时创建/销毁一个新的 DetailsViewController。所以,我的didSelectRowAtIndexPath: 通常看起来像:

        - (void) didSelectRowAtIndexPath:(NSIndexPath*)indexPath
        {
          NSInteger selectedRow = indexPath.row;
        
          // Create a new view controller
          DetailsViewController *tmpVC = [[DetailsViewController alloc] initWithNibName:@"foo" bundle:nil];
        
          // Tell our new view controller what data it should be using
          tmpVC.tableData = [self.someArrayOfData objectAtIndex:selectedRow];
        
          // Push view controller and release it
          [self.navigationController pushViewController:tmpVC animated:YES];
          [tmpVC release];
        }
        

        此示例假定您在 ItemsViewController 中拥有两个视图控制器所需的所有数据 - 情况可能并非如此..?

        无论如何,通过这种方式,您的 DetailsViewController 会自动加载数据。当您点击“返回”返回 ItemsViewController 时,UINavigationController 将释放它并销毁它。然后,当用户点击不同的单元格时,我们再次运行这段代码,创建一个带有全新数据的全新控制器 - 当然,当它显示时,它会自动加载数据 - 它以前从未显示过。

        听起来您在代码中所做的可能是将DetailsViewController 保留为ItemsViewController 类的属性,然后重用该对象。如果您关心分配,这也可以工作(例如,如果它是一个非常“重”的分配来制作 DetailsViewController),但我认为调用 reloadData 的最佳位置不在类本身内部 - 但是而不是来自 ItemsViewController 的didSelectRowAtIndexPath: 方法。

        我提倡创建/销毁方法而不是“享元模式”方法的原因是它使您的代码更加独立 - 视图控制器之间的链接越少越好。当然,ItemsViewController 将始终依赖并了解 DetailsViewController,但不一定非要反过来 - 如果您将 reloadData 调用添加到 viewWillAppear:animated:,您将隐式添加非代码依赖项他们俩。您知道当 ItemsViewController 是导航堆栈中的“父级”时,这是正确的行为——但是如果您突然开始在不需要重新加载的应用程序的其他部分重用该视图怎么办?这对一个人来说是一个性能问题,而且,它是一种隐藏的依赖关系,有一天可能会导致令人讨厌的跟踪错误。因此,如果确实只需要 1 个 DetailsViewController(而不是我每次都重新创建它的第一个想法),我会让 Details 变得愚蠢并让 Items 包含所有复杂性。

        【讨论】:

        • 你对我所做的假设是完全正确的。我需要更多地考虑分配和解除分配细节视图的相对成本。嗯..
        • 您的数据数组有多大? Items 一般有多少行?详细信息中有多少数据?
        【解决方案5】:

        我建议将 reloadData 和 setTitle 放在 viewDidLoad 和 setter 中 - 我假设您在 DetailsViewController 中设置了一个属性来更改表的数据源。所以 viewDidLoad 会重新加载并设置标题,如果属性已经设置,setter 会重新加载并设置标题,如果 isViewLoaded 并且新值与旧值不同。

        - (void)setSmth:(SmthClass *)value {
             if (value == smth)  // if they are the same and SmthClass is immutable,
                                 // otherwise use isEqual and [self.tableView reloadData]
                                 // before returning...
                 return;
             id pointer = smth;  // if it's a retain property
             smth = [value retain];
             [pointer release];      // release after retain just to be extra safe
        
             if ([self isViewLoaded]) { 
                  [self.tableView reloadData];
                  [self setTitle:title];
             }
        }
        
        - (void)viewDidLoad {
             if (smth) {
                 [self.tableView reloadData]; // maybe redundant...
                 [self setTitle:title];
             }
        }
        

        或者您可以使用键值观察(NSKeyValueObserving 协议)来观察您的属性并在通知时重新加载数据...

        【讨论】:

        • 这不会减少调用 reloadData 的次数,而且会增加额外的开销。但我认为这是解决方案的一部分(尤其是与下面的 Altealice 结合使用)
        • 另外,每次显示控制器时都不会调用 viewDidLoad。
        猜你喜欢
        • 1970-01-01
        • 2012-11-11
        • 2011-09-13
        • 2012-06-13
        • 2018-10-30
        • 1970-01-01
        • 2010-10-08
        • 2012-06-22
        • 1970-01-01
        相关资源
        最近更新 更多