15

我有一个NSTableView绑定到一个NSArrayController. 的属性绑定到一个NSArrayController。一切都很好。contentSetNSMutableSet

现在我想使用内置的动画NSTableView来删除行。我可以做到这一点,- [NSTableView removeRowsAtIndexes:withAnimation:]并且该行很快就会动画化,但是我从 tableview 中删除的对象仍然挂在NSMutableSet支持 tableview 的对象中。显然我需要删除它。如果我尝试通过NSArrayController'removeObject:方法将其删除,则该对象会立即从 tableview 中消失,这意味着动画不会发生或在中途被切断。

绑定可以创造奇迹并使事情变得如此简单,但是当同时使用绑定和NSTableView动画时,保持数据源和 tableview 同步的正确方法到底是什么?答案还应该解决如何NSTableView使用动画将行添加到边界。

4

6 回答 6

9

动画完成后需要立即更新模型:

@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 上测试。

于 2015-09-08T00:57:14.830 回答
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 中发生了一些变化?所有这些都是从主线程运行的,这可能是为什么?(您是否尝试过在 a 中调用代码dispatch_async(dispatch_get_main_queue(), block())

于 2013-11-09T06:13:16.843 回答
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"];
于 2014-04-10T23:23:35.323 回答
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];
}
于 2021-07-17T14:56:54.013 回答
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 )
    }
}
于 2015-08-19T20:50:22.257 回答
-1

从评论中对您的问题的讨论看来,没有一个简单的“绑定”适当的答案。因此,作为一种解决方法,您不能在开始动画后立即发出简单的“performSelector:withObject:afterDelay”命令吗?显然,延迟时间将近似于动画记录的方式,并且在选择器中是您从 NSMutableSet 中删除对象的位置。

于 2012-12-03T12:10:10.870 回答