Eri*_*ric 15 grand-central-dispatch swift
到目前为止,我已经看到了这些问题的答案(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()
Run Code Online (Sandbox Code Playgroud)
输出:
This is printed only on the first call to test()
This is printed for each call to test()
Run Code Online (Sandbox Code Playgroud)
但是等一下.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()
Run Code Online (Sandbox Code Playgroud)
输出:
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()
Run Code Online (Sandbox Code Playgroud)
所以,dispatch_once是没有用的,如果我们我可以改变的价值token!和转弯token,因为它需要类型为常量并不简单UnsafeMutablePointer<dispatch_once_t>.
那么我们应该放弃dispatch_onceSwift吗?有一种更安全的方式只执行一次代码吗?
Ada*_*ght 21
一名男子去看医生,然后说:"医生,当我踩到我的脚上时会疼." 医生回答说:"别这样做".
如果您故意改变您的调度令牌,那么是 - 您将能够执行两次代码.但是如果你解决了旨在以任何方式阻止多次执行的逻辑,你就能够做到.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 Code Online (Sandbox Code Playgroud)
Jer*_*man 17
由闭包初始化的静态属性是懒惰运行的,最多只运行一次,所以这只打印一次,尽管被调用了两次:
/*
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.")
}
Run Code Online (Sandbox Code Playgroud)
示例运行:
~/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.
Run Code Online (Sandbox Code Playgroud)
我认为最好的方法是根据需要懒惰地构建资源。Swift 让这一切变得简单。
有几种选择。如前所述,您可以使用闭包在类型中初始化静态属性。
然而,最简单的选择是定义一个全局变量(或常量)并用闭包初始化它,然后在需要初始化代码发生一次的任何地方引用该变量:
let resourceInit : Void = {
print("doing once...")
// do something once
}()
Run Code Online (Sandbox Code Playgroud)
另一种选择是将类型包装在函数中,以便在调用时读取更好。例如:
func doOnce() {
struct Resource {
static var resourceInit : Void = {
print("doing something once...")
}()
}
let _ = Resource.resourceInit
}
Run Code Online (Sandbox Code Playgroud)
您可以根据需要对此进行更改。例如,您可以根据需要使用私有全局和内部或公共函数,而不是使用函数的内部类型。
但是,我认为最好的方法是确定您需要初始化哪些资源并将它们懒惰地创建为全局或静态属性。