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