Подтвердить что ты не робот

Использование анимации NSTableView с привязками

У меня есть NSTableView, связанный с NSArrayController. Свойство NSArrayController contentSet привязано к NSMutableSet. Все отлично работает.

Теперь я хочу использовать анимации, встроенные в NSTableView, для удаления строк. Я могу сделать это с помощью - [NSTableView removeRowsAtIndexes:withAnimation:], и строка быстро анимируется, однако объект, который я удалил из tableview, все еще висит в NSMutableSet, который поддерживает табличное представление. Очевидно, мне нужно удалить его. Если я попытаюсь удалить его с помощью метода NSArrayController removeObject:, тогда объект немедленно исчезнет из таблицы, что означает, что анимация не возникает или отключается на полпути.

Привязки творят чудеса и делают вещи намного проще, но что именно является правильным методом для хранения источника данных и таблицы в синхронизации, когда используются как привязки, так и анимация NSTableView? В ответе также должно быть рассмотрено, как добавить строки в связанный NSTableView с помощью анимаций.

4b9b3361

Ответ 1

Модель должна быть обновлена ​​сразу после завершения анимации:

@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.

Ответ 2

Я только что играл с этим на 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())?

Ответ 3

Когда вы удаляете элемент из 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"];

Ответ 4

Нашел себя в этой же ситуации: хотел как можно больше использовать привязки (свести к минимуму количество кода клея) и по-прежнему добавлять небольшие фрагменты логики, специфичные для моего приложения.

У меня есть NSTableView, который предоставляет кнопку удаления на каждой из своих строк. Кнопка удаления подключена к IBAction в моем подклассе NSViewController. Таблица должным образом привязана к NSArrayController (выполняется в моей раскадровке через IB). Мне также нужна анимация при удалении строки.

Я использую 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 )
    }
}

Ответ 5

Кажется, из обсуждения в комментарии к вашему вопросу, что нет простого "привязки" соответствующего ответа. Таким образом, вы можете просто создать простую команду "performSelector: withObject: afterDelay" сразу после запуска анимации? Очевидно, что время задержки будет приблизительным, как журнал принимает анимацию, а в селекторе - это место, где вы удаляете объект из NSMutableSet.