到目前为止,我已经看到了这些问题的答案(1,2,3)建议使用GCD是dispatch_once
这样的:
var token: dispatch_once_t = 0 func test() { dispatch_once(&token) { print("This is printed only on the first call to test()") } print("This is printed for each call to test()") } test()
输出:
This is printed only on the first call to test() This is printed for each call to test()
但是等一下.token
是一个变量,所以我可以很容易地做到这一点:
var token: dispatch_once_t = 0 func test() { dispatch_once(&token) { print("This is printed only on the first call to test()") } print("This is printed for each call to test()") } test() token = 0 test()
输出:
This is printed only on the first call to test() This is printed for each call to test() This is printed only on the first call to test() This is printed for each call to test()
所以,dispatch_once
是没有用的,如果我们我可以改变的价值token
!和转弯token
,因为它需要类型为常量并不简单UnsafeMutablePointer
.
那么我们应该放弃dispatch_once
Swift吗?有一种更安全的方式只执行一次代码吗?
一名男子去看医生,然后说:"医生,当我踩到我的脚上时会疼." 医生回答说:"别这样做".
如果您故意改变您的调度令牌,那么是 - 您将能够执行两次代码.但是如果你解决了旨在以任何方式阻止多次执行的逻辑,你就能够做到.dispatch_once
仍然是确保代码只执行一次的最佳方法,因为它处理初始化和竞争条件下的所有(非常)复杂的极端情况,简单的布尔值不会覆盖.
如果您担心某人可能会意外地重置令牌,您可以将其包装在一个方法中并使其显而易见,因为它可能是后果.像下面这样的东西会将令牌范围扩展到方法,并阻止任何人在没有认真努力的情况下更改它:
func willRunOnce() -> () { struct TokenContainer { static var token : dispatch_once_t = 0 } dispatch_once(&TokenContainer.token) { print("This is printed only on the first call") } }
由闭包初始化的静态属性是懒惰运行的,最多只运行一次,所以这只打印一次,尽管被调用了两次:
/* run like: swift once.swift swift once.swift run to see both cases */ class Once { static let run: Void = { print("Behold! \(__FUNCTION__) runs!") return () }() } if Process.arguments.indexOf("run") != nil { let _ = Once.run let _ = Once.run print("Called twice, but only printed \"Behold\" once, as desired.") } else { print("Note how it's run lazily, so you won't see the \"Behold\" text now.") }
示例运行:
~/W/WhenDoesStaticDefaultRun> swift once.swift
Note how it's run lazily, so you won't see the "Behold" text now.
~/W/WhenDoesStaticDefaultRun> swift once.swift run
Behold! Once runs!
Called twice, but only printed "Behold" once, as desired.