Swift function can be called only once

You can do smth like:

class Once {

  var already: Bool = false

  func run(@noescape block: () -> Void) {
    guard !already else { return }

    block()
    already = true
  }
}

and than use it like

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


A simple solution is to take advantage of lazy variables in the following way:

// Declare your "once-only" closure like this
private lazy var myFunction: Void = {
    // Do something once
}()

...

// Then to execute it, just call
_ = myFunction

This ensures that the code inside the myFunction closure is only executed the first time that the program runs _ = myFunction


Edit: Another approach is to use so called "dispatch once tokens". This comes from Objective-C and was available in Swift until Swift 3. It is still possible to make it work, however you will need to add a little bit of custom code. You can find more information on this post -> dispatch_once after the Swift 3 GCD API changes


Edit2: Should be _ = myFunction and not _ = myFunction(), as JohnMontgomery pointed out.


One possible technique is to put the code into the initializer of a static type property, which is guaranteed to be lazily initialized only once (even when accessed across multiple threads simultaneously):

func theFunction() {
    struct Once {
        static let once = Once()
        init() {
            print("This should be executed only once during the lifetime of the program")
        }
    }
    _ = Once.once
}

(Compare Singleton in the "Using Swift with Cocoa and Objective-C" reference.)

Example:

print("Call #1")
theFunction()
print("Call #2")
theFunction()
print("Done")

Output:

Call #1
This should be executed only once during the lifetime of the program
Call #2
Done

You might use a static bool inside a struct nested into the function itself doing so:

func theFunction(){
    struct Holder { static var called = false }

    if !Holder.called {
        Holder.called = true
        //do the thing
    }
}