I have a NSTableView
that is bound to a NSArrayController
. The NSArrayController
\'s contentSet
property is bound to a
Found myself in this same situation: wanted to use bindings as much as possible (minimize amount of glue code) and still be able to add small pieces of logic specific to my app.
I have an NSTableView that exposes a delete button on every one of its rows. The delete button is hooked up to an IBAction on my NSViewController subclass. The table is properly bound to an NSArrayController (done in my Storyboard via IB). I also wanted an animation on row deletion.
I'm using swift (but I think it should be pretty straightforward to translate this to objective-c). The only way I got this to work with bindings, was to use a timer to deferred the deletion of the object from the NSArrayController (using half a second delay below - change it to suit your needs):
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 )
}
}
It seems from discussion in the comments to your question that there isn't a simple "bindings" appropriate answer. So as a work-around couldn't you just issue a simple "performSelector:withObject:afterDelay" command right after you start you animation? Obviously the delay time would be approximate of how log the animation takes and in the selector is where you remove the object from the NSMutableSet.
When you remove item from NSTableView, you should also update your mutableSet variable. When you remove the item from mutableSet, you need to tell NSArrayController to update. To do this
[self willchangeValueForKey:@"mutableSet"]; //your mutableset variable Name
[self.myTable removeRowsAtIndexes:[NSIndexSet indexSetWithIndex:selectedRow] withAnimation:NSTableViewAnimationSlideUp];
[mutableSet removeObject:item];
[self didchangeValueForKey:@"mutableSet"];
I've just been playing with this on OS X 10.9, and everything seems to be working fine for me. Here's my code (I have a '-' button in each row of my view-based table:
- (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];
}
Maybe something changed in 10.9? All of this is running from the main thread, could that be why? (Have you tried calling the code inside a dispatch_async(dispatch_get_main_queue(), block())
?
The model needs to be updated right after the animation is complete:
@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)
})
}
Works in my app with bindings. Tested on OS X 10.9, 10.10 & 10.11.