Skip to content

Instantly share code, notes, and snippets.

@MartinJNash
Last active August 29, 2015 14:23
Show Gist options
  • Save MartinJNash/2c856305d63333614015 to your computer and use it in GitHub Desktop.
Save MartinJNash/2c856305d63333614015 to your computer and use it in GitHub Desktop.
A Swift class to dispatch blocks either the first time and or all but the first time.
import Foundation
public final class FirstOrAllOtherDispatcher {
private var firstTimeOnlyBlock: (()->Void)?
private var allOtherTimesBlock: (()->Void)?
public init(firstTime: ()->Void) {
self.firstTimeOnlyBlock = firstTime
self.allOtherTimesBlock = nil
}
public init(allButFirstBlock: ()->Void) {
self.firstTimeOnlyBlock = nil
self.allOtherTimesBlock = allButFirstBlock
}
public init(firstTime: ()->Void, allOtherTimes: ()->Void) {
self.firstTimeOnlyBlock = firstTime
self.allOtherTimesBlock = allOtherTimes
}
private var once: dispatch_once_t = 0
private func makeSwizzle() {
dispatch_once(&once, {
let myclass: AnyClass = object_getClass(self)
let originalMethod = class_getInstanceMethod(myclass, "doing")
let swizzledMethod = class_getInstanceMethod(myclass, "realDoing")
method_exchangeImplementations(originalMethod, swizzledMethod)
})
}
/// This has to be dynamic, can be private
private dynamic func doing() {
makeSwizzle()
firstTimeOnlyBlock?()
}
/// Has to be at least internal or be private dynamic
private dynamic func realDoing() {
allOtherTimesBlock?()
}
public func call() {
doing()
}
}
let tt = FirstOrAllOtherDispatcher(firstTime: { print("Fisrt and once") }, allOtherTimes: { print("Other time") })
tt.call()
tt.call()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment