Swift函数只能调用一次

时间:2018-02-02 22:18:26

标签: swift function

编写一段只能执行一次的代码的最简单方法是什么?

我知道一种方法,但有问题。

首先,我写了一个布尔变量,它具有负值,但可以设置为正值,之后不能更改

 var hasTheFunctionCalled : Bool = false {
   didSet{
       hasTheFunctionCalled = true
   }
} 

然后在其中编写函数和代码:

func theFunction(){
   if !hasTheFunctionCalled{
      //do the thing
   }
   hasTheFunctionCalled = true
 } 

但问题是变量可以从范围内的其他地方更改,这个解决方案看起来并不那么简单和具体。

6 个答案:

答案 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