Swift 3中dispatch_once代码转换求助:遇‘dispatch_once不可用’报错
解决Swift 3中
dispatch_once不可用的问题 嘿,这个问题我太熟悉了!Swift 3开始苹果正式弃用了dispatch_once,因为Swift语言本身已经提供了更简洁、更安全的方式来实现“只执行一次”的逻辑,不需要再依赖GCD的C API啦。我给你几个实用的替代方案:
方案1:利用Swift静态属性的懒加载特性(推荐)
Swift的静态属性默认是线程安全的,而且只会在第一次被访问时初始化,完美替代dispatch_once的功能。把你的一次性执行代码放到一个静态属性的闭包里就行:
func willRunOnceCoach() { struct TokenContainer { static let runOnce: Void = { print("This is printed only on the first call") self.createCochMark() }() } // 第一次调用时会触发闭包执行,后续调用只会访问已经初始化好的静态属性,不会重复执行 _ = TokenContainer.runOnce }
原理说明:
- 嵌套结构体
TokenContainer的静态属性runOnce是Void类型,闭包会在第一次访问runOnce时执行 - Swift保证静态属性的初始化是原子性的,完全不用担心线程安全问题
- 后续调用这个方法时,
runOnce已经初始化完成,只会做一次简单的取值操作,不会重复执行闭包里的代码
方案2:类/全局级别的一次性初始化
如果你的一次性逻辑是类级别的(比如初始化类的全局配置),可以直接把代码放到类的静态属性里:
class CoachManager { // 类级别的一次性初始化代码 static let classSetup: Void = { print("CoachManager setup runs only once") // 这里放类的全局初始化逻辑 }() func doSomething() { // 触发一次性初始化 _ = CoachManager.classSetup } }
方案3:手动加锁实现(不推荐,仅作参考)
如果你习惯了GCD的思路,也可以用锁+标志位来实现,但代码会更繁琐,不如静态属性优雅:
func willRunOnceCoach() { // 静态变量保存执行状态,只会初始化一次 static var hasExecuted = false static let executionLock = NSLock() // 加锁保证线程安全 executionLock.lock() defer { executionLock.unlock() } // 已经执行过就直接返回 guard !hasExecuted else { return } // 标记为已执行 hasExecuted = true // 执行你的逻辑 print("This is printed only on the first call") self.createCochMark() }
总结
优先用方案1,这是Swift官方推荐的方式,代码简洁、线程安全,完全符合Swift的语言设计理念。
内容的提问来源于stack exchange,提问作者naveen
相关产品推荐
相关产品推荐

