How to pause a CADisplayLink?

我的未来我决定 提交于 2019-12-23 02:40:32

问题


I have a problem in my app. What I want to happened is when I click button2, it disappears and stops moving. What's happening now is that when I click button2, it disappears but doesn't stop moving (even while its hidden).Any help? Code:

@IBOutlet var label: UILabel!
@IBOutlet var label2: UILabel!    
@IBOutlet var label3: UILabel!
@IBOutlet var button2: UIButton!
@IBAction func button3(sender: UIButton) {
    label.hidden = false
button2.hidden = true
}
@IBOutlet var button4: UIButton!
@IBAction func button5(sender: UIButton) {
button4.hidden = true
label2.hidden = false
}
@IBAction func button1(sender: UIButton) {
   label.hidden = true
    label2.hidden = true
   button2.hidden = false
      button2.frame = CGRectMake(120, 400, 100, 100)
    let displayLink = CADisplayLink(target: self, selector: "handleDisplayLink:")
    displayLink.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
    let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), 2 * Int64(NSEC_PER_SEC))
    dispatch_after(time, dispatch_get_main_queue()) { 
        self.button4.hidden = false
    self.button4.frame = CGRectMake(120, 400, 100, 100)
    let displayLink1 = CADisplayLink(target: self, selector: "handleDisplayLink1:")
        displayLink1.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)}
    }
func handleDisplayLink(displayLink: CADisplayLink) {
    var buttonFrame = button2.frame
    buttonFrame.origin.y += -2
    button2.frame = buttonFrame
    if button2.frame.origin.y <= 50 {
        displayLink.invalidate()
        label3.hidden = false
        button2.hidden = true
    }
}
func handleDisplayLink1(displayLink1: CADisplayLink) {
    var button4Frame = button4.frame
    button4Frame.origin.y += -2
    button4.frame = button4Frame
    if button4.frame.origin.y <= 50 {
        displayLink1.invalidate() 
        label3.hidden = false
        button4.hidden = true
    }
}
override func viewDidLoad() {
    super.viewDidLoad()
  label.hidden = true
    button2.hidden = true
   label2.hidden = true
    button4.hidden = true
   label3.hidden = true
    // Do any additional setup after loading the view, typically from a nib.  
}

Thank you. Anton


回答1:


This is exceedingly confusing because it's unclear as to the relationship between the two outlets called button2 and button4 and the @IBAction methods called button1, button3, and button5? How many buttons do you actually have? Two? Four? Five? And what these various labels? If they're not part of the question, they shouldn't be included in the code snippet.

But if it's button3 or button5 that's getting called, then yes, those hide the button, but don't invalidate the display link, so the display link will progress. If you want it to stop the display link, then you have to call invalidate:

var displayLink: CADisplayLink?
var displayLink1: CADisplayLink?

@IBAction func button3(sender: UIButton) {
    label.hidden = false
    button2.hidden = true
    displayLink?.invalidate()
    displayLink = nil
}

@IBAction func button5(sender: UIButton) {
    button4.hidden = true
    label2.hidden = false
    displayLink1?.invalidate()
    displayLink1 = nil
}

This obviously means that button5 should be using these properties, not using local variables for displayLink and displayLink1:

@IBAction func button1(sender: UIButton) {
    label.hidden = true
    label2.hidden = true
    button2.hidden = false
    button2.frame = CGRectMake(120, 400, 100, 100)
    // NB: No `let` on the next line
    displayLink = CADisplayLink(target: self, selector: "handleDisplayLink:")
    displayLink?.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)

    let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), 2 * Int64(NSEC_PER_SEC))
    dispatch_after(time, dispatch_get_main_queue()) {
        self.button4.hidden = false
        self.button4.frame = CGRectMake(120, 400, 100, 100)
        // NB: No `let` on the next line
        self.displayLink1 = CADisplayLink(target: self, selector: "handleDisplayLink1:")
        self.displayLink1?.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
    }
}

A few additional observations:

  1. If you're using auto-layout, you should be very wary about just adjusting the frame of these controls. In auto-layout, if you happen to do anything to trigger the constraints engine to be applied (e.g. update the text of these labels), the controls will move back to where the constraints defined them to be.

  2. You're changing the frame of these controls, moving them 2 points per call. That's might end up with stuttering or changing of speeds of the animation UI as your app gets more complicated. You shouldn't update a fixed amount per call of the display link handler, but rather use some time based functions to determine how much time has elapsed and calculate the new coordinates from that.

  3. I personally wouldn't use display links for this kind of stuff. I would just use the standard UIView.animateWithDuration, and then when I wanted to stop button2 from moving, I would:

    let currentButton2Frame = button2.layer.presentationLayer()!.frame
    button2.layer.removeAllAnimations()
    button2.frame = currentButton2Frame
    

    This identifies where it is, mid-animation, stops the animation, and resets the frame to the coordinates previously identified. This avoids the complexities of display links.




回答2:


You need to store a reference to the display links you create in your button click handler. So create class level properties for them:

@IBAction func button5(sender: UIButton) {
    button4.hidden = true
    label2.hidden = false
}

// new code here:
var displayLink: CADisplayLink?
var displayLink1: CADisplayLink?

Then invalidate them before you create them, in case an instance already exists:

@IBAction func button1(sender: UIButton) {
   displayLink?.invalidate()
   displayLink1?.invalidate()

   displayLink = CADisplayLink(target: self, selector: "handleDisplayLink:")
   displayLink1 = CADisplayLink(target: self, selector: "handleDisplayLink1:")

   displayLink = 
   label.hidden = true
   label2.hidden = true
   button2.hidden = false

   // ... rest of your method
}


来源:https://stackoverflow.com/questions/34211832/how-to-pause-a-cadisplaylink

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