Cocoa dispatch_once per instance

Your requirements can't be satisfied. dispatch_once can only be used on memory that's never been written to before, and you have no way to guarantee this with instance variables. Greg Parker says so, and he's the guy who would know.

Instead, use the code in your question, but wrap it in a @synchronized block.

If you really want to avoid adding instance variables, you could use a separate singleton to manage a mutable set. You'd have to register instances with it and remove them on deallocation. Make sure this helper class only holds weak references; see NSMapTable and NSMapTableWeakMemory.