简体   繁体   中英

How to add a time delay in swift

I am writing an interactive game in swift, and I need to know how to add a pause in between repetitive actions. The way I have to do this is in a for loop. As follows:

for i in 1...10 {
    println("Hello!")
}

Can anyone find a way to modify this code so that it prints one "Hello" per second?

Also, if swift for loops are instantly returning, i don't think that delay code would work in there, so here is another iterative solution using functions that should work if the for loop doesn't.

func printer() {
    println("Hello")
    delay()
}

func delay() {
    //delay code goes here
    printer()
}

Any help would be greatly appreciated.

Thanks.

Try this

for i in 1...10{
    var timeToDelay = Double(i)
    delay(timeToDelay) {
        println("Hello")
    }
}

func delay(delay:Double, closure:()->()) {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW,Int64(delay * Double(NSEC_PER_SEC))),dispatch_get_main_queue(), closure)
}

Welcome to SO.

In your viewDidLoad for example :

var aDelay = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector:Selector("printer"), userInfo: nil, repeats: true)

And have your method in the same view controller :

func printer() {
    println("Hello")
}

This should work as requested. However, this might not be the best thing depending on what game you're making, etc...

The right solution depends on what you need to do on a periodic basis. If you're updating the user interface (for example, adding a ticking timer), then you need something different than if you're doing something in the background (like saving the game state).

If you're updating the user interface every second, then it's probably best to use a CADisplayLink to update the interface periodically. Let's say you have a label timeLabel that you need to update. Here's how you could do it:

class ViewController: UIViewController {
    @IBOutlet weak var timeLabel: UILabel!
    var startTime: CFTimeInterval?
    var link: CADisplayLink?

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        self.link = CADisplayLink(self, selector: Selector("updateTime:"))
        self.link.addToRunLoop(NSRunLoop.currentRunLoop(), NSDefaultRunLoopMode)
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)

        self.link?.invalidate()
        self.link = nil
    }

    func updateTime(link: CADisplayLink) {
        if startTime == nil {
            startTime = link.timestamp
        }
        let elapsed = Int(link.timestamp - startTime!)
        self.timeLabel?.text = "\(elapsed)"
    }
}

If you're just doing a background job (like saving game state... or printing hello), then using an NSTimer or grand central dispatch will work well. You don't want to use an NSTimer or grand central dispatch if you're updating the UI, because these mechanisms aren't as precise.

Grand Central Dispatch

fun work() {
    // do work here
}

func workEverySecond() {
    let d = dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_SEC))
    let repeatWork: () -> Void = {
        work()
        dispatch_after(timeDelay, dispatch_get_main_queue(), repeatWork)
    }
    repeatWork()
}

NSTimer

var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector:Selector("work"), userInfo: nil, repeats: true)

func work() {
    // do work here
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM