I recently found myself needing to do some work in -viewDidAppear:, but not the first time. Only when the view comes back on screen after being off screen, like when popping a navigation stack.

Doing something once is no problem in cocoa since we have dispatch_once in GCD. But I need to do the opposite. I need something like dispatch_all_but_first.

I was able to come up with a several solutions after some discussion on Twitter.

var onceToken: dispatch_once_t = 0

func someMethod() {

    var isFirst = false
    dispatch_once(&onceToken, {
        isFirst = true
    })
    
    if isFirst {
        // first time
    } else {
        // all but first time
    }
    
}

We can then encapsulate this logic into a class. This helps us to avoid littering our other code with dispatch tokens and if/else logic blocks.

public final class AllButFirst {
    
    let block: ()->Void

    init(block: ()->Void) {
        self.block = block
    }
    
    private var once: dispatch_once_t = 0
    
    public func call() {
        var isFirst = false
        dispatch_once(&once, {
            isFirst = true
        })
        
        if !isFirst {
            self.block()
        }
    }
    
}

Which you can use like this:

var subsequent = AllButFirst(block: { self.updateData() })
subsequent.call() // nothing
subsequent.call() // calls