问题
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:
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 thetext
of these labels), the controls will move back to where the constraints defined them to be.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.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