我有NSTableView
绑定到NSArrayController
。 NSArrayController
的{{1}}属性绑定到contentSet
。一切都很好。
现在我想使用内置于NSMutableSet
的动画来删除行。我可以使用NSTableView
执行此操作,并且该行可以快速设置动画,但是我从tableview中删除的对象仍然在支持tableview的- [NSTableView removeRowsAtIndexes:withAnimation:]
中停留。显然我需要删除它。如果我尝试通过NSMutableSet
的{{1}}方法删除它,那么该对象会立即从tableview中消失,这意味着动画不会发生或在中途被切断。
绑定工作奇迹并使事情变得如此简单,但是当使用绑定和NSArrayController
动画时,究竟什么是保持数据源和tableview同步的正确方法?答案还应该解决如何使用动画将行添加到绑定removeObject:
。
答案 0 :(得分:8)
模型需要在动画完成后立即更新:
@IBAction func onRemoveClick(sender: AnyObject?) {
let selection = listController.selectionIndexes
NSAnimationContext.runAnimationGroup({
context in
self.tableView.removeRowsAtIndexes(selection, withAnimation: .EffectFade | .SlideUp)
}, completionHandler: {
self.listController.removeObjectsAtArrangedObjectIndexes(selection)
})
}
在我的应用程序中使用绑定。测试OS X 10.9,10.10& 10.11。
答案 1 :(得分:1)
我刚刚在OS X 10.9上玩过这个,而似乎对我来说都很好。 这是我的代码(我的基于视图的表的每一行都有一个' - '按钮:
- (IBAction)removeRow:(id)sender {
NSUInteger selectedRow = [self.myTable rowForView:sender];
if (selectedRow == -1) {
return;
}
[self.myTable removeRowsAtIndexes:[NSIndexSet indexSetWithIndex:selectedRow] withAnimation:NSTableViewAnimationSlideUp];
[self.myArrayHookedUpToTheNSArrayController removeObjectAtIndex:selectedRow];
}
10.9可能有些变化?所有这一切都是从主线程运行的,这可能是为什么? (您是否尝试在dispatch_async(dispatch_get_main_queue(), block())
内调用代码?
答案 2 :(得分:0)
从NSTableView中删除项目时,还应该更新mutableSet变量。当您从mutableSet中删除该项时,您需要告诉NSArrayController更新。要做到这一点
[self willchangeValueForKey:@"mutableSet"]; //your mutableset variable Name
[self.myTable removeRowsAtIndexes:[NSIndexSet indexSetWithIndex:selectedRow] withAnimation:NSTableViewAnimationSlideUp];
[mutableSet removeObject:item];
[self didchangeValueForKey:@"mutableSet"];
答案 3 :(得分:0)
发现自己处于同样的情况:想尽可能多地使用绑定(最小化胶水代码量),并且仍然能够添加特定于我的应用程序的小块逻辑。
我有一个NSTableView,它在每一行上都有一个删除按钮。删除按钮连接到我的NSViewController子类上的IBAction。该表已正确绑定到NSArrayController(通过IB在我的Storyboard中完成)。我还想要删除行的动画。
我使用swift(但我认为将其转换为objective-c应该非常简单)。我使用绑定工作的唯一方法是使用计时器推迟从NSArrayController删除对象(使用下面的半秒延迟 - 根据您的需要更改它):
import Cocoa
class ProjectsController: NSViewController {
@IBOutlet var arrayController: NSArrayController!
@IBOutlet weak var tableView: NSTableView!
@IBAction func deleteRow( object: AnyObject ) {
let row = tableView.rowForView( object as! NSView )
if ( row > -1 ) {
let indexSet = NSIndexSet( index:row )
tableView.removeRowsAtIndexes( indexSet, withAnimation: NSTableViewAnimationOptions.EffectFade )
NSTimer.scheduledTimerWithTimeInterval( 0.5, target: self, selector: "rowDeleted:", userInfo: row, repeats: false )
}
}
func rowDeleted( timer:NSTimer ) {
let row = timer.userInfo as! Int
arrayController.removeObjectAtArrangedObjectIndex( row )
}
}
答案 4 :(得分:0)
Big Sur 有一些更新。要获得流畅的动画,必须使用 NSAnimationContext
。在没有它的情况下运行 NSTableView
将重新加载其所有数据。
- (IBAction)delete:(nullable id)sender
{
NSIndexSet *indexSet = [self.tableView indexesToProcessForContextMenu];
[NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull context) {
context.allowsImplicitAnimation = YES;
[self.tableView removeRowsAtIndexes:indexSet withAnimation:NSTableViewAnimationEffectFade | NSTableViewAnimationSlideUp];
} completionHandler:^{
[self.resultsArrayController removeObjectsAtArrangedObjectIndexes:indexSet];
}];
//CODE THAT CAUSES TABLE RELOAD ON BIG SUR
//[self.tableView removeRowsAtIndexes:indexSet withAnimation:NSTableViewAnimationEffectFade | NSTableViewAnimationSlideUp];
//[self.resultsArrayController removeObjectsAtArrangedObjectIndexes:indexSet];
}
答案 5 :(得分:-1)
从你的问题的评论中讨论,似乎没有一个简单的“绑定”适当的答案。因此,在开始动画之后,你不能直接发出一个简单的“performSelector:withObject:afterDelay”命令吗?显然,延迟时间将近似于动画所记录的日志,而选择器则是从NSMutableSet中删除对象的位置。