Espandendo la risposta di Tod Cunningham sopra, ho aggiunto un altro metodo che rende il token automaticamente da file, funzione e linea.
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()
}
}
Così può essere più semplice di chiamare:
DispatchQueue.once {
setupUI()
}
e si può ancora indicare un gettone se lo si desidera:
DispatchQueue.once(token: "com.me.project") {
setupUI()
}
Suppongo che si possa ottenere una collisione se si dispone di lo stesso file in due moduli. Peccato che non ci sia #module
Eventuali duplicati: [Dove DISP atch_once in Swift 3?] (http://stackoverflow.com/q/37801407/957768) – rickster
In base alle risposte https://stackoverflow.com/a/38311178/1648724 e https://stackoverflow.com/a/ 39983813/1648724, ho creato un CocoaPod per farlo: ['pod 'SwiftDispatchOnce', '~> 1.0''] (https://github.com/JRG-Developer/SwiftDispatchOnce) Saluti. :] –