dispatch_once after the Swift 3 GCD API changes

后端 未结 9 1708
忘掉有多难
忘掉有多难 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:06

    While using lazy initialized globals can make sense for some one time initialization, it doesn't make sense for other types. It makes a lot of sense to use lazy initialized globals for things like singletons, it doesn't make a lot of sense for things like guarding a swizzle setup.

    Here is a Swift 3 style implementation of dispatch_once:

    public extension DispatchQueue {
    
        private static var _onceTracker = [String]()
    
        /**
         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:@noescape(Void)->Void) {
            objc_sync_enter(self); defer { objc_sync_exit(self) }
    
            if _onceTracker.contains(token) {
                return
            }
    
            _onceTracker.append(token)
            block()
        }
    }
    

    Here is an example usage:

    DispatchQueue.once(token: "com.vectorform.test") {
        print( "Do This Once!" )
    }
    

    or using a UUID

    private let _onceToken = NSUUID().uuidString
    
    DispatchQueue.once(token: _onceToken) {
        print( "Do This Once!" )
    }
    

    As we are currently in a time of transition from swift 2 to 3, here is an example swift 2 implementation:

    public class Dispatch
    {
        private static var _onceTokenTracker = [String]()
    
        /**
         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 token: String, @noescape block:dispatch_block_t) {
            objc_sync_enter(self); defer { objc_sync_exit(self) }
    
            if _onceTokenTracker.contains(token) {
                return
            }
    
            _onceTokenTracker.append(token)
            block()
        }
    
    }
    

提交回复
热议问题