Swift NSTimer and IBOutlet Issue

拜拜、爱过 提交于 2019-12-13 05:00:07

问题


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?


回答1:


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
    }
}



回答2:


Yes, this is well known behavior of auto layout. If you do anything that causes the auto layout engine to reapply the constraints to the view (such as updating the score), any adjustments to layout-related properties will be lost, reset to their values as dictated by the constraints.

As Vacawama pointed out, you could turn off auto layout. Alternatively, rather than manually changing the frame in your timer routine, you could instead create an IBOutlet for the constraints, themselves, and you can them modify the constraint's constant property and then call layoutIfNeeded. That way, if you happen to do something else that triggers the constraints, everything will be fine.



来源:https://stackoverflow.com/questions/26227093/swift-nstimer-and-iboutlet-issue

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