How do I run a function with a parameter every 5 seconds in Swift?

三世轮回 提交于 2019-12-11 23:21:25

问题


I want to execute the following function every 5 seconds. I have seen the other answers to related questions that say to use NSTimer.scheduledTimerWithTimeInterval but that only works for functions without any arguments.

The function:

func sayHello(name: String) {
    println("Hey \(name)!")
}

This is the code I tried:

var timer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: Selector("sayHello(\(name))"), userInfo: nil, repeats: true)

But it crashes the app with the error:

Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[Jake.SwiftApp sayHello(jake)]: unrecognized
selector sent to instance 0x7fcd515640a0'

How do I run the function with the one input parameter?


回答1:


I believe that you can have your function take the NSTimer as an argument, which then allows you to send your data in the userInfo like so.

var timer : NSTimer = NSTimer(timeInterval: 5.0, target: self, selector: Selector("sayHello:"), userInfo: "Jake", repeats: true)

func sayHello(timer: NSTimer) {
     println(timer.userInfo)
}

I haven't been able to test this so the timer might be malformed, but I think the logic is right.




回答2:


The problem is, when you set up the selector for the NSTimer to fire, you have to pass just the name of the method.

Right now, you're dynamically building a string and trying to point to a method called:

"sayHello(jake)"

Which doesn't exist. In fact, in can't exist. This doesn't even make sense.

The sayHello() fun would look like this if you're adding it as a selector with a string:

"sayHello:"

But just fixing this will still be problems. An NSTimer's target can take zero or one arguments. And if it does take an argument, it expects that argument to be an NSTimer. When NSTimer's fire and call their target, they pass themselves as a parameter.

So, we need to setup our method like this:

func sayHello(timer: NSTimer) {
    // do stuff
}

And now we pass Selector("sayHello:") for our selector argument.

In order to pass any sort of arguments in, we have to package them into the NSTimer's userInfo property, which is of type AnyObject?. Then, within the method our timer calls, we can access this property.

class ExampleClass {
    var timer: NSTimer?

    var userName: String? {
        set {
            self.timer?.userInfo = newValue
        }
        get {
            return self.timer?.userInfo as? String
        }
    }

    func timerTick(timer: NSTimer) {
        if let userName = timer.userInfo as? String {
            self.sayHello(userName)
        }
    }

    func sayHello(userName: String) {
        println("Hello " + userName + "!")
    }

    func startTimer(#interval: NSTimeInterval = 5.0, userName: String? = nil) {
        self.timer = NSTimer.scheduledTimerWithTimeInterval(interval, 
            target: self, 
            selector: Selector("timerTick:"), 
            userInfo: userName, 
            repeats: true
        )
    }
}

From here, any time you want to change the name the timer is carrying around, you can just do:

self.userName = "Jake"


来源:https://stackoverflow.com/questions/30927488/how-do-i-run-a-function-with-a-parameter-every-5-seconds-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!