It’s supposed to invoke your block when all the animations in the current transaction have completed. It doesn’t; it runs it as soon as the transaction is committed. Le sigh.
It does appear to do it from the main runloop at least, as documented. So there is technically a delay, as a consequence of that scheduling. Not helpful though.
Update: turns out that you have to set the completion block before calling +[SCNTransaction begin]
. Grrr. Undocumented behaviour #bajillion+1.