Erweitern auf Tod Cunningham Antwort oben, habe ich eine andere Methode hinzugefügt, die das Token automatisch aus Datei, Funktion und Zeile macht.
public extension DispatchQueue {
private static var _onceTracker = [String]()
public class func once(file: String = #file, function: String = #function, line: Int = #line, block:(Void)->Void) {
let token = file + ":" + function + ":" + String(line)
once(token: token, block: block)
}
/**
Executes a block of code, associated with a unique token, only once. The code is thread safe and will
only execute the code once even in the presence of multithreaded calls.
- parameter token: A unique reverse DNS style name such as com.vectorform.<name> or a GUID
- parameter block: Block to execute once
*/
public class func once(token: String, block:(Void)->Void) {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
if _onceTracker.contains(token) {
return
}
_onceTracker.append(token)
block()
}
}
So kann es einfacher sein zu nennen:
DispatchQueue.once {
setupUI()
}
und Sie können nach wie vor ein Token angeben, wenn Sie wollen:
DispatchQueue.once(token: "com.me.project") {
setupUI()
}
Ich nehme an, Sie eine Kollision bekommen könnte, wenn Sie die gleiche Datei in zwei Modulen. Schade, dass es nicht #module
Mögliche doppelte: [Whither disp atch_once in Swift 3?] (http://stackoverflow.com/q/37801407/957768) – rickster
Basierend auf den Antworten https://stackoverflow.com/a/38311178/1648724 und https://stackoverflow.com/a/ 39983813/1648724, ich habe dafür einen CocoaPod erstellt: ['pod 'SwiftDispatchOnce', '~> 1.0''] (https://github.com/JRG-Developer/SwiftDispatchOnce) Cheers. :] –