编写一段只能执行一次的代码的最简单方法是什么?
我知道一种方法,但有问题。
首先,我写了一个布尔变量,它具有负值,但可以设置为正值,之后不能更改
var hasTheFunctionCalled : Bool = false {
didSet{
hasTheFunctionCalled = true
}
}
然后在其中编写函数和代码:
func theFunction(){
if !hasTheFunctionCalled{
//do the thing
}
hasTheFunctionCalled = true
}
但问题是变量可以从范围内的其他地方更改,这个解决方案看起来并不那么简单和具体。
答案 0 :(得分:6)
一个简单的解决方案是以下列方式利用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
编辑:另一种方法是使用所谓的"发送一次令牌"。它来自Objective-C,在Swift中可用,直到Swift 3.它仍然可以使它工作,但是你需要添加一些自定义代码。你可以在这篇文章中找到更多信息 - > dispatch_once after the Swift 3 GCD API changes
Edit2:应该是_ = myFunction
而不是_ = myFunction()
,正如JohnMontgomery指出的那样。
答案 1 :(得分:3)
一种可能的技术是将代码放入静态类型属性的初始化器中,保证只能懒惰地初始化一次(即使同时跨多个线程访问):
func theFunction() {
struct Once {
static let once = Once()
init() {
print("This should be executed only once during the lifetime of the program")
}
}
_ = Once.once
}
(比较{"使用Swift与Cocoa和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
答案 2 :(得分:2)
你可以在嵌入到函数本身的结构中使用静态bool:
func theFunction(){
struct Holder { static var called = false }
if !Holder.called {
Holder.called = true
//do the thing
}
}
答案 3 :(得分:1)
根据您在方法中的操作:您可以检查最终结果是否已经完成:
e.g。如果你实例化一个类,检查它是否与nil不同
答案 4 :(得分:1)
您还可以使用UserDefaults,并且知道默认的UserDefault Bool为false:
if !UserDefaults.standard.bool(forKey: "ExecuteOnce") {
func()
UserDefaults.standard.set(true, forKey: "ExecuteOnce")
}
此代码将只执行一次。
答案 5 :(得分:0)
您可以执行以下操作:
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()
}
}
}
ref:https://dev.to/onmyway133/how-to-run-action-once-in-swift-3k7o