Swift 函数只能调用一次
Swift function can be called only once
写一段只能执行一次的代码最简单的方法是什么?
我知道一个方法,但有一个问题。
首先,我写了一个布尔变量,它有负值,但可以设置为正值,之后不能改变
var hasTheFunctionCalled : Bool = false {
didSet{
hasTheFunctionCalled = true
}
}
然后编写函数和里面的代码:
func theFunction(){
if !hasTheFunctionCalled{
//do the thing
}
hasTheFunctionCalled = true
}
但问题是变量可以从范围内的其他地方更改,这个解决方案看起来并不那么简单和具体。
一个简单的解决方案是通过以下方式利用 lazy
变量:
// Declare your "once-only" closure like this
private lazy var myFunction: Void = {
// Do something once
}()
...
// Then to execute it, just call
_ = myFunction
这确保 myFunction
闭包中的代码仅在程序第一次运行时执行 _ = myFunction
编辑:另一种方法是使用所谓的"dispatch once tokens"。这来自 Objective-C 并在 Swift 中可用,直到 Swift 3。仍然可以让它工作,但是您需要添加一些自定义代码。您可以找到有关此 post ->
的更多信息
Edit2:正如 JohnMontgomery 指出的那样,应该是 _ = myFunction
而不是 _ = myFunction()
。
取决于您在方法中所做的事情:您可以检查最终结果是否已经完成:
例如如果你实例化一个class,检查它是否不同于nil
您可以在嵌套到函数本身的结构中使用静态布尔值:
func theFunction(){
struct Holder { static var called = false }
if !Holder.called {
Holder.called = true
//do the thing
}
}
一种可能的技术是将代码放入静态类型的初始化程序中属性,保证只延迟初始化一次(即使同时跨多个线程访问):
func theFunction() {
struct Once {
static let once = Once()
init() {
print("This should be executed only once during the lifetime of the program")
}
}
_ = Once.once
}
(比较 "Using Swift with Cocoa and Objective-C" 参考中的 Singleton。)
示例:
print("Call #1")
theFunction()
print("Call #2")
theFunction()
print("Done")
输出:
Call #1
This should be executed only once during the lifetime of the program
Call #2
Done
你也可以使用UserDefaults,默认UserDefault Bool为false的知识:
if !UserDefaults.standard.bool(forKey: "ExecuteOnce") {
func()
UserDefaults.standard.set(true, forKey: "ExecuteOnce")
}
这段代码只会执行一次。
你可以这样做:
class Once {
var already: Bool = false
func run(@noescape block: () -> Void) {
guard !already else { return }
block()
already = true
}
}
然后像
一样使用它
class ViewController: UIViewController {
let once = Once()
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
once.run {
cameraMan.setup()
}
}
}
参考:https://dev.to/onmyway133/how-to-run-action-once-in-swift-3k7o
写一段只能执行一次的代码最简单的方法是什么?
我知道一个方法,但有一个问题。
首先,我写了一个布尔变量,它有负值,但可以设置为正值,之后不能改变
var hasTheFunctionCalled : Bool = false {
didSet{
hasTheFunctionCalled = true
}
}
然后编写函数和里面的代码:
func theFunction(){
if !hasTheFunctionCalled{
//do the thing
}
hasTheFunctionCalled = true
}
但问题是变量可以从范围内的其他地方更改,这个解决方案看起来并不那么简单和具体。
一个简单的解决方案是通过以下方式利用 lazy
变量:
// Declare your "once-only" closure like this
private lazy var myFunction: Void = {
// Do something once
}()
...
// Then to execute it, just call
_ = myFunction
这确保 myFunction
闭包中的代码仅在程序第一次运行时执行 _ = myFunction
编辑:另一种方法是使用所谓的"dispatch once tokens"。这来自 Objective-C 并在 Swift 中可用,直到 Swift 3。仍然可以让它工作,但是您需要添加一些自定义代码。您可以找到有关此 post ->
Edit2:正如 JohnMontgomery 指出的那样,应该是 _ = myFunction
而不是 _ = myFunction()
。
取决于您在方法中所做的事情:您可以检查最终结果是否已经完成:
例如如果你实例化一个class,检查它是否不同于nil
您可以在嵌套到函数本身的结构中使用静态布尔值:
func theFunction(){
struct Holder { static var called = false }
if !Holder.called {
Holder.called = true
//do the thing
}
}
一种可能的技术是将代码放入静态类型的初始化程序中属性,保证只延迟初始化一次(即使同时跨多个线程访问):
func theFunction() {
struct Once {
static let once = Once()
init() {
print("This should be executed only once during the lifetime of the program")
}
}
_ = Once.once
}
(比较 "Using Swift with Cocoa and Objective-C" 参考中的 Singleton。)
示例:
print("Call #1")
theFunction()
print("Call #2")
theFunction()
print("Done")
输出:
Call #1 This should be executed only once during the lifetime of the program Call #2 Done
你也可以使用UserDefaults,默认UserDefault Bool为false的知识:
if !UserDefaults.standard.bool(forKey: "ExecuteOnce") {
func()
UserDefaults.standard.set(true, forKey: "ExecuteOnce")
}
这段代码只会执行一次。
你可以这样做:
class Once {
var already: Bool = false
func run(@noescape block: () -> Void) {
guard !already else { return }
block()
already = true
}
}
然后像
一样使用它class ViewController: UIViewController {
let once = Once()
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
once.run {
cameraMan.setup()
}
}
}
参考:https://dev.to/onmyway133/how-to-run-action-once-in-swift-3k7o