使用带有绑定的NSTableView动画

时间:2012-11-24 13:22:23

标签: objective-c cocoa nstableview

我有NSTableView绑定到NSArrayControllerNSArrayController的{​​{1}}属性绑定到contentSet。一切都很好。

现在我想使用内置于NSMutableSet的动画来删除行。我可以使用NSTableView执行此操作,并且该行可以快速设置动画,但是我从tableview中删除的对象仍然在支持tableview的- [NSTableView removeRowsAtIndexes:withAnimation:]中停留。显然我需要删除它。如果我尝试通过NSMutableSet的{​​{1}}方法删除它,那么该对象会立即从tableview中消失,这意味着动画不会发生或在中途被切断。

绑定工作奇迹并使事情变得如此简单,但是当使用绑定和NSArrayController动画时,究竟什么是保持数据源和tableview同步的正确方法?答案还应该解决如何使用动画将行添加到绑定removeObject:

6 个答案:

答案 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中删除对象的位置。