Understanding -[NSArrayController add:]

A fairly common question on the Cocoa-dev mailing list, is how to know when ‑[NSArrayController add:] has finished doing its work. The simple is answer is: you can’t. The docs state:

Special Considerations

Beginning with Mac OS X v10.4 the result of this method is deferred until the next iteration of the runloop so that the error presentation mechanism (see Error Responders and Error Recovery) can provide feedback as a sheet.

Talk of “the result of this method” kinda implies there’s some sort of callback available, but there isn’t. To my understanding, if you really want to deal with this, your only choice is to effectively re-implement -add: yourself. Fortunately I’ve done this for you:

Looking at this, I think it becomes understandable why -add:’s result is deferred. If committing editing happens to fail, then Cocoa will present that error as a sheet. The delegate is only called once that alert has been dismissed. This does raise the question (rdar://11270645) though of how Apple’s implementation handles such failures. Does it go ahead and add a new object anyway? Are the pending changes discarded? Or perhaps it bails out, hopefully at least beeping to indicate the failure.

Cocoa has a rather odd design for sheet-handling whereby you cannot immediately present one after another without calling -orderOut: on the first. Alternatively, you can put off presenting the sheet until the next spin of the runloop. It seems from the docs that NSArrayController anticipates such a scenario by delaying its call to commit editing, just in case a sheet does need to be presented. I’ve assumed that you’re in control of your code enough to order out a previous sheet manually if needed, and so left it out of the code.

I think the only other thing worth noting is that you can’t quite apply this same code as an extension to NSTreeController, since its -newObject method doesn’t have the smarts to deal with creating managed objects. You’d need to override -newObject yourself too, or provide equivalent logic inside of -addWithCompletionHandler:

© Mike Abdullah 2007-2015