Search code examples
swiftnstimer

Swift Timer error when function has arguments


I'm trying to make a function that activates every one second, which adds 1 to a variable (texttimer) and adds a letter to a string (typedStory), which is displayed on a label (storyLabel).

Everything worked fine until I added an argument (finalStory) to the function. Now I'm getting an an error:

-[__NSCFTimer substringToIndex:]: unrecognized selector sent to instance

Here's the code I have:

func textTypeWelcome(finalStory: NSString){
    var newTimer2 = Timer.scheduledTimer(timeInterval: 0.05, target: self, selector: #selector(GameScene.textTypeWelcome), userInfo: finalStory, repeats: false)
    texttimer += 1
    typedStory = finalStory.substring(to: texttimer)
    storyLabel.text = typedStory

}

The code works, however doesn't do what I want if I remove the argument and put userInfo to nil.

Anyone know of a solution? Thanks!


Solution

  • No, that cannot work, the action method takes the timer as parameter – what the error message tells you – and you get finalStory from the userInfo parameter.

    func textTypeWelcome(timer: Timer) {
        let finalStory = timer.userInfo as! String
        var newTimer2 = Timer.scheduledTimer(timeInterval: 0.05, target: self, selector: #selector(GameScene.textTypeWelcome), userInfo: finalStory, repeats: false)
        texttimer += 1
        typedStory = finalStory.substring(to: texttimer)
        storyLabel.text = typedStory
    }
    

    Try this out in a Playground

    class Foo  : NSObject {
    
        let string = "Hello World"
        var counter = 1
    
        var typedStory = ""
    
        var timer = Timer()
    
        override init() {
            super.init()
            timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(timerFired), userInfo: nil, repeats: true)
            print("timer started")
        }
    
        func timerFired(timer : Timer) {
    
            typedStory = string.substring(to: string.index(string.startIndex, offsetBy: counter))
            print(typedStory)
            if typedStory == string {
                timer.invalidate()
                print("timer stopped")
            } else {
                counter += 1
            }
        }
    }
    
    let foo = Foo()
    

    You have to add the lines

    import PlaygroundSupport
    PlaygroundPage.current.needsIndefiniteExecution = true
    

    to allow asynchronous API