1
votes

I have an animation that is running fine until I change the button text from start to stop. The text changes but the animation itself disappears. What am I doing wrong?


import UIKit

class ViewController: UIViewController {

    var counter = 1

    var timer = NSTimer()

    var isAnimating = false

    @IBOutlet weak var button: UIButton!

    @IBOutlet weak var frogsImage: UIImageView!

    @IBAction func updateImage(sender: AnyObject) {

        if isAnimating == false {
            timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("doAnimation"), userInfo: nil, repeats: true)
            isAnimating = true
            button.setTitle("Stop Jumping", forState: UIControlState.Normal)

        } else {
            timer.invalidate()
            isAnimating = false
            button.setTitle("Start Jumping", forState: UIControlState.Normal)
        }

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

    func doAnimation() {
        if counter == 4 {
            counter = 1
        } else {
            counter++
        }

        frogsImage.image = UIImage(named: "frame\(counter).png"
        )

    }


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

    override func viewDidLayoutSubviews() {

        // Hiding off the screen
        frogsImage.center = CGPointMake(frogsImage.center.x - 400, frogsImage.center.y)

    }

    override func viewDidAppear(animated: Bool) {
        UIView.animateWithDuration(1) { () -> Void in
            self.frogsImage.center = CGPointMake(self.frogsImage.center.x + 400, self.frogsImage.center.y)
        }
    }


}
3

3 Answers

0
votes

The animation is stopped because you're invalidating the timer.

After invalidating the timer, you should restart it again. So, you'll have the animation running again.

Hope this helps.

0
votes

Here are a few things I would do differently, but I don't have it running in a project so I can't guarantee it will all work.

class ViewController: UIViewController {

    var counter = 1

    var timer = NSTimer()

    var isAnimating = false
    var didSetup = false
    var didAnimateIn = false

    @IBOutlet weak var button: UIButton!
    @IBOutlet weak var frogsImage: UIImageView!
    @IBAction func updateImage(sender: AnyObject) {

        if isAnimating == false {
            timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("doAnimation"), userInfo: nil, repeats: true)
            isAnimating = true
            button.setTitle("Stop Jumping", forState: UIControlState.Normal)

        } else {
            timer.invalidate()
            isAnimating = false
            button.setTitle("Start Jumping", forState: UIControlState.Normal)
        }

    }

    func doAnimation() {
        if counter == 4 {
            counter = 1
        } else {
            counter++
        }

        frogsImage.image = UIImage(named: "frame\(counter).png"
        )

    }

    override func viewDidLayoutSubviews() {
        // Change this to always call super first
        super.viewDidLayoutSubviews()

        // Only do this once 
        if !didSetup {
            didSetup = true
            frogsImage.center = CGPointMake(frogsImage.center.x - 400, frogsImage.center.y)
        }

    }

    override func viewDidAppear(animated: Bool) {
        // Change this to always call super
        super.viewDidAppear(animated)

        // Only do this once, after setup
        if didSetup && !didAnimateIn {
            didAnimateIn = true
            UIView.animateWithDuration(1) { () -> Void in
                self.frogsImage.center = CGPointMake(self.frogsImage.center.x + 400, self.frogsImage.center.y)
            }
        }
    }
}
0
votes

What's happening is that your image is going back 400 pixels to the left again. You can check this for yourself by changing the leftward shift to 40px instead and running the app. This is due to the fact that viewDidLayoutSubviews is called in several instances and resets the location of the image to whatever you specified originally.

In other words, the method is called when

  1. the app is opened
  2. again prior to the animation
  3. when the button is tapped.

How I suggest bypassing this is to add a count variable like so

import UIKit

class ViewController : UIViewController {
    var viewCount = 0 //ADD THIS

    var counter = 1

    var timer = NSTimer()

    var isAnimating = false

    @IBOutlet weak var button: UIButton!

    @IBOutlet weak var frogsImage: UIImageView!

    @IBAction func updateImage(sender: AnyObject) {

        if isAnimating == false {
            timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("doAnimation"), userInfo: nil, repeats: true)
            isAnimating = true
            button.setTitle("Stop Jumping", forState: UIControlState.Normal)

        } else {
            timer.invalidate()
            isAnimating = false
            button.setTitle("Start Jumping", forState: UIControlState.Normal)
        }

    }

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

    func doAnimation() {
        if counter == 4 {
            counter = 1
        } else {
            counter++
        }

        frogsImage.image = UIImage(named: "frame\(counter).png")
    }


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

    override func viewDidLayoutSubviews() {

        // ADD THIS IF BLOCK
        if viewCount < 2 {
            frogsImage.center = CGPointMake(frogsImage.center.x - 400, frogsImage.center.y)
            viewCount++
        }

    }

    override func viewDidAppear(animated: Bool) {
        UIView.animateWithDuration(1) { () -> Void in
            self.frogsImage.center = CGPointMake(self.frogsImage.center.x + 400, self.frogsImage.center.y)
        }
    }
}