Collin Stover Collin Stover - 3 months ago 20
iOS Question

2.2 Scheduled Timer Returns "View Controller has No Member..."

I am at my wit's end here trying to figure out how to get this NSTimer to work. Pasting my entire code for clarity's sake. The important part is bolded.

import UIKit
import QuartzCore
import Foundation

class ViewController: UIViewController {
@IBOutlet weak var outerCircle: UIImageView!

@IBOutlet weak var innerCircle: UIImageView!

@IBOutlet weak var instructionLabel: UILabel!

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.


var timer: NSTimer!


timer = NSTimer.scheduledTimerWithTimeInterval(5, target: self, selector: #selector(ViewController.runTimedCode), userInfo: nil, repeats: true)


func runTimedCode() {


UIView.animateWithDuration(5, delay:0, options:[], animations: {
//Inhale
self.innerCircle.transform = CGAffineTransformMakeScale(3.5, 3.5)
self.instructionLabel.text = "Inhale"

}, completion: { finish in
//Exhale
UIView.animateWithDuration(5, delay:0, options:[], animations: {

self.innerCircle.transform = CGAffineTransformMakeScale(1, 1)
self.instructionLabel.text = "Exhale"
}, completion: nil)
})

}


}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}


}


I want what is in the "runTimedCode()" to run every 10 seconds. I am currently getting an error on:

timer = NSTimer.scheduledTimerWithTimeInterval(5, target: self, selector: #selector(ViewController.runTimedCode), userInfo: nil, repeats: true)


The error says "Type 'ViewController' has no member 'runTimedCode'.

When I take ViewController. out, I get a different error: Use of local variable 'runTimedCode' before its declaration.

And finally, when I move that line to the bottom of the code, I get "Argument of '#selector' refers to a method that is not exposed to Objective-C.

I feel like I have honestly tried everything to get this timer to work. I have looked at every thread imaginable. Do I have some kind of fundamental misunderstanding of how the timer functions?

Answer

Everyone is right, you defined your runTimedCode function inside your viewDidLoad so it's in the wrong scope. Also you should avoid nesting animations inside the completion blocks. Try using the code I have prepared for you below.

import Foundation

class ViewController: UIViewController {

    // MARK: Outlets

    @IBOutlet weak var outerCircle: UIImageView!
    @IBOutlet weak var innerCircle: UIImageView!
    @IBOutlet weak var instructionLabel: UILabel!

    // MARK: Properties

    var timer: NSTimer?

    // MARK: Lifecycle

    override func viewDidLoad() {

        super.viewDidLoad()

        timer = NSTimer.scheduledTimerWithTimeInterval(5,
            target: self,
            selector: #selector(timerDidFinish),
            userInfo: nil,
            repeats: true
        )
    }

    // MARK: NSTimer

    func timerDidFinish() {

        UIView.animateWithDuration(5, delay: 0, options: [.Autoreverse], animations: {
            self.innerCircle.transform = CGAffineTransformMakeScale(3.5, 3.5)
            self.instructionLabel.text = "Inhale"
        }, completion: nil)
    }
}