Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I execute code once and only once in Swift?

The answers I've seen so far (1, 2, 3) recommend using GCD's dispatch_once thus:

var token: dispatch_once_t = 0
func test() {
    dispatch_once(&token) {
        print("This is printed only on the first call to test()")
    }
    print("This is printed for each call to test()")
}
test()

Output:

This is printed only on the first call to test()
This is printed for each call to test()

But wait a minute. token is a variable, so I could easily do this:

var token: dispatch_once_t = 0
func test() {
    dispatch_once(&token) {
        print("This is printed only on the first call to test()")
    }
    print("This is printed for each call to test()")
}
test()

token = 0

test()

Output:

This is printed only on the first call to test()
This is printed for each call to test()
This is printed only on the first call to test()
This is printed for each call to test()

So dispatch_once is of no use if we I can change the value of token! And turning token into a constant is not straightforward as it needs to of type UnsafeMutablePointer<dispatch_once_t>.

So should we give up on dispatch_once in Swift? Is there a safer way to execute code just once?

like image 543
Eric Avatar asked Dec 10 '15 13:12

Eric


People also ask

How is swift code executed?

You can run the Swift REPL from the command line and enter Swift code directly into it. Whenever you enter valid Swift code in the REPL, it will immediately compile and run it. Lets play around with the Swift REPL a bit. You can access previous lines that you've entered using $R0 etc.

How can I make a function execute every second in Swift?

You can use one like this: var timer = NSTimer() override func viewDidLoad() { scheduledTimerWithTimeInterval() } func scheduledTimerWithTimeInterval(){ // Scheduling timer to Call the function "updateCounting" with the interval of 1 seconds timer = NSTimer.


1 Answers

A man went to the doctor, and said "Doctor, it hurts when I stamp on my foot". The doctor replied, "So stop doing it".

If you deliberately alter your dispatch token, then yes - you'll be able to execute the code twice. But if you work around the logic designed to prevent multiple execution in any way, you'll be able to do it. dispatch_once is still the best method to ensure code is only executed once, as it handles all the (very) complex corner cases around initialisation and race conditions that a simple boolean won't cover.

If you're worried that someone might accidentally reset the token, you can wrap it up in a method and make it as obvious as it can be what the consequences are. Something like the following will scope the token to the method, and prevent anyone from changing it without serious effort:

func willRunOnce() -> () {
    struct TokenContainer {
        static var token : dispatch_once_t = 0
    }

    dispatch_once(&TokenContainer.token) {
        print("This is printed only on the first call")
    }
}
like image 164
Adam Wright Avatar answered Oct 01 '22 10:10

Adam Wright