dispatch_once after the Swift 3 GCD API changes

后端 未结 9 1728
忘掉有多难
忘掉有多难 2020-11-28 20:48

What is the new syntax for dispatch_once in Swift after the changes made in language version 3? The old version was as follows.

var token: dispa         


        
9条回答
  •  天涯浪人
    2020-11-28 21:16

    Expanding on Tod Cunningham's answer above, I've added another method which makes the token automatically from file, function, and line.

    public extension DispatchQueue {
        private static var _onceTracker = [String]()
    
        public class func once(file: String = #file,
                               function: String = #function,
                               line: Int = #line,
                               block: () -> Void) {
            let token = "\(file):\(function):\(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. or a GUID
         - parameter block: Block to execute once
         */
        public class func once(token: String,
                               block: () -> Void) {
            objc_sync_enter(self)
            defer { objc_sync_exit(self) }
    
            guard !_onceTracker.contains(token) else { return }
    
            _onceTracker.append(token)
            block()
        }
    }
    

    So it can be simpler to call:

    DispatchQueue.once {
        setupUI()
    }
    

    and you can still specify a token if you wish:

    DispatchQueue.once(token: "com.hostname.project") {
        setupUI()
    }
    

    I suppose you could get a collision if you have the same file in two modules. Too bad there isn't #module

提交回复
热议问题