Search code examples
swiftnstimeriboutlet

Swift NSTimer and IBOutlet Issue


I'm using NSTimer to update an image's position on the screen to give the illusion of movement. It's a flappy bird clone I'm creating to learn Swift. Anyway, I'm also updating an outlet by displaying an incrementing Int as the score. However, every time I update the Int and the corresponding outlet, the images on the screen reset to their starting point (bird and tubes). Very odd. Has anyone else come across this? What am I doing wrong?

@IBOutlet weak var tube1: UIImageView!
@IBOutlet weak var bird1: UIImageView!
@IBOutlet weak var score: UILabel!

func startTimer() {
    timer = NSTimer.scheduledTimerWithTimeInterval(0.02, target: self, selector: Selector("update"), userInfo: nil, repeats: true)
}

func update() {
    bird1.center=CGPointMake(50,bird1.center.y+CGFloat(num));
    tube1.center=CGPointMake(tube1.center.x-CGFloat(num2),tube1.center.y);
    if(tube1.center.x<(-40)){
        tube1.center.x=screenWidth;//variable set outside this method
        tube1.center.y=0;//will be random
        updateMyScore();
    }
}

func updateMyScore(){
    myScore=++;

    score.text="Score: \(myScore)"
}

The weird thing is if I comment out the score.text="Score:(myScore)" line everything works fine, but I'd like to have the score show on the screen. Any suggestions?


Solution

  • AutoLayout is running and resetting the position of your images. It is running because you are updating your UILabel. There are 2 ways you can deal with this:

    1. Disable AutoLayout OR
    2. Store the positions of your tubes and pipes in properties and then set them in an override of viewDidLayoutSubviews().

    Here is how you might implement option #2:

    @IBOutlet weak var tube1: UIImageView!
    @IBOutlet weak var bird1: UIImageView!
    @IBOutlet weak var score: UILabel!
    var tube1center: CGPoint?
    var bird1center: CGPoint?
    
    func startTimer() {
        timer = NSTimer.scheduledTimerWithTimeInterval(0.02, target: self, selector: Selector("update"), userInfo: nil, repeats: true)
    }
    
    func update() {
        bird1.center=CGPointMake(50,bird1.center.y+CGFloat(num));
        tube1.center=CGPointMake(tube1.center.x-CGFloat(num2),tube1.center.y);
        if(tube1.center.x<(-40)){
            tube1.center.x=screenWidth;//variable set outside this method
            tube1.center.y=0;//will be random
            updateMyScore();
        }
        bird1center = bird1.center
        tube1center = tube1.center
    }
    
    func updateMyScore(){
        myScore=++;
    
        score.text="Score: \(myScore)"
    }
    
    override func viewDidLayoutSubviews() {
        if let newcenter = tube1center {
            tube1.center = newcenter
        }
        if let newcenter = bird1center {
            bird1.center = newcenter
        }
    }