使用NSTableView在OS X上模仿动画iPhone最近的呼叫列表



我试图非常接近地模仿iPhone手机应用程序最近调用TableView的功能,使用OS X上的NSTableView。所需的功能是单击一个按钮,TableView 将从显示所有最近的呼叫切换到显示未接的呼叫的子集,并且,我希望有您在 iPhone 上看到的动画,其中行的外观和消失是动画。

正在使用基于视图的 NSTableView,并且我在我的视图控制器中通过手动数据源和委托(不使用 cocoa 绑定)非常简单地连接了它。

除了尝试删除行以显示"未接"呼叫的子集外,一切正常。如果我只是重建作为表视图数据源的 NSMutableArray,然后调用 reloadData,它就可以完美地工作。但这没有给我动画。下面是未动画的版本,它使表视图和数据源NSMutableArray完全同步,表视图中的内容正确,但没有动画:

- (IBAction)showMissed:(id)sender {    
  NSMutableIndexSet *indices = [NSMutableIndexSet indexSet];
  Call *call;
  for (call in callsArray) {
    if (!call.missed) {
      [indices addIndex:[callsArray indexOfObject:call]];
    }
  }
  if ([indices count] > 0) {
    [callsArray removeObjectsAtIndexes:indices];
    [self.recentsTableView reloadData];
  }
}

当我尝试使用 NSTableView removeRowsAtIndexes:indices withAnimation: 方法来获取我想要的动画时,我遇到了一些非常奇怪的行为。这是动画显示错过的方法:

- (IBAction)showMissed:(id)sender {    
  NSMutableIndexSet *indices = [NSMutableIndexSet indexSet];
  Call *call;
  for (call in callsArray) {
    if (!call.missed) {
      [indices addIndex:[callsArray indexOfObject:call]];
    }
  }
  if ([indices count] > 0) {
    [callsArray removeObjectsAtIndexes:indices];
    [self.recentsTableView removeRowsAtIndexes:indices withAnimation:NSTableViewAnimationSlideUp];
  }
}

我在该方法的动画版本中使用的逻辑是从Apple的TableViewPlaygound示例代码中提取的。

当我运行这段代码时,我得到两个奇怪的结果。首先,TableView 不仅显示"未接"的调用 - 它显示正确的行数(即 TableView 中的行数等于标记为未接的 Call 对象数),但行中显示的实际对象有些未接,有些没有错过。

更奇怪的是,在动画版本运行后,callsArray 包含所有 Call 对象,就好像 [callsArray removeObjectsAtIndexes:indices]; 语句根本不存在一样。似乎removeRowsAtIndexes:indices withAnimation:方法以某种方式弄乱了我的数据源数组的内容并使整个事情失灵。

FWIW,我的动画 showAll 方法基本上与上述使用insertRowsAtIndexes:indices withAnimation:相反的方法似乎完美运行。

我做错了什么?

数据源数组和表视图之间的同步中一定存在一些损坏。我通过在方法顶部添加 reloadData 调用来修复它。这是固定的 showMissing 方法:

- (IBAction)showMissed:(id)sender {    
  NSMutableIndexSet *indices = [NSMutableIndexSet indexSet];
  Call *call;
  [self.recentsTableView reloadData];
  for (call in callsArray) {
    if (!call.missed) {
      [indices addIndex:[callsArray indexOfObject:call]];
    }
  }
  if ([indices count] > 0) {
    [callsArray removeObjectsAtIndexes:indices];
    [self.recentsTableView removeRowsAtIndexes:indices withAnimation:NSTableViewAnimationSlideUp];
  }
}

最新更新