Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cocoa dispatch_once per instance

How to use dispatch_once, so the given code is executed once, per instance lifetime.

Equivalent would be to have a property inside the object, and use it like this:

- (void)viewWillAppear:(..).. {

   // ...

   if (self.isDispatched == NO) {
      // ...
      self.isDispatched = YES;
   }

}

But I don't want to use an extra property, but the dispatch_once_t or similar.

like image 329
Peter Lapisu Avatar asked Aug 08 '14 10:08

Peter Lapisu


2 Answers

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.

like image 195
Steven Fisher Avatar answered Nov 16 '22 04:11

Steven Fisher


For those of you who are curious and as an extra tip, for me this approach has been useful for this purpose:

class SomeVC : UIViewController {
    private var token: dispatch_once_t = 0

    public override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        dispatch_once(&token) { () -> Void in
            self.doSomethingOnce()
        }

    }
}

By not declaring a static var it has the expected behaviour. That being said, this is definitely NOT RECOMMENDED for any serious project, since in the Docs (as your well said) it states:

The predicate must point to a variable stored in global or static scope. The result of using a predicate with automatic or dynamic storage (including Objective-C instance variables) is undefined.

If we don't want to run into any future weird bugs and undefined behaviour I would just stick to what Apple says. But it's still nice to play around with these things, isn't it? =)

like image 27
Robertibiris Avatar answered Nov 16 '22 03:11

Robertibiris