A Moveable Beast

Implementing reordering table views is something of a first-time obstacle in Cocoa. The basic gist is you take responsibility for dragging from and to the table view in question, and thereby implicitly support drag reordering. This technique is demonstrated by Apple’s DragNDropOutlineView example.

Faced with the desire to implement such functionality in a bindings-oriented application (FlexTime), I realized it would make sense to have the dragging handled by a the NSArrayController, which is already handling so much of the behavior associated with the table view.

RSRTVArrayController implements a subclass of NSArrayController whose responsibilities are extended to provide simple row reordering via Drag-and-Drop. The basic gist is:

Drop this one class into your project.

Drag the header file to Interface Builder

Set it as the custom class on an array controller instance

Connect the dataSource and delegate outlets from the table view to the controller.

Connect the oTableView outlet from the controller to the table view.

Et voila!

You can also temporarily disable reordering by calling “setDraggingEnabled:” on the controller. I do this for instance in FlexTime while the routine is running so users can’t completely confuse my world.

Update: Rick Fillion pointed out a possible day-ruining bug in the code, which will only rear it’s head if you happen to be assigning all ownership of your model objects to the array controller. Since the “move” code accomplishes the move by removing and then inserting an object from the array, it turns out that once it’s removed, it’s deallocated if nothing else in your app is retaining it! So the workaround is to be retain the object while moving it, and then release it. Thanks for reporting that, Rick. The downloadable class is now updated.