Friday, April 22, 2016

OS X app freeze when closing window during CALayer animation

Leave a Comment

I made a custom NSControl to use it as a custom layer backed button.

When the MyButton instance receives mouseDown and mouseUp events it changes its backgroundLayer's backgroundColorand its textLayer's foregroundColor.

It's using layers so the changes are implicitly animated.

But on mouseUp if the mouse is inside the MyButton's instance frame I call the linked action through sendAction(_:to:) method.

I linked the action to a method closing the current window and opening another one but sometimes the app freeze after the second window shows up.

I tried several things and it seems related to the layer animations, maybe something to do before closing the window that I'm not aware of.

You can find an example project here : https://dl.dropboxusercontent.com/u/378166/CALayerFreeze.zip
(note that you'll sometimes have to try several times before the bug occurs)

Here's the code for MyButton.

class MyButton: NSControl {     let title = "Click me!"      // Init     required init?(coder: NSCoder) {         super.init(coder: coder)         setup()     }      deinit {         trackingAreas.forEach { self.removeTrackingArea($0) }     }      // Layer + Tracking Area configuration     var backgroundLayer = CALayer()     var textLayer = CATextLayer()      func setup() {         wantsLayer = true          backgroundLayer.frame = NSRect(origin: .zero, size: frame.size)         backgroundLayer.backgroundColor = NSColor.whiteColor().CGColor         layer?.addSublayer(backgroundLayer)          textLayer.frame = NSRect(origin: .zero, size: frame.size)         textLayer.string = title         textLayer.foregroundColor = NSColor.blackColor().colorWithAlphaComponent(0.64).CGColor         layer?.addSublayer(textLayer)          addTrackingArea(             NSTrackingArea(                 rect: bounds,                 options: [.MouseEnteredAndExited, .EnabledDuringMouseDrag, .ActiveInKeyWindow],                 owner: self,                 userInfo: nil             )         )     }      // States     private func normal() {         // ——— COMMENTING THIS MAKES THE BEACHBALL GO AWAY         backgroundLayer.backgroundColor = NSColor.whiteColor().CGColor         textLayer.foregroundColor = NSColor.blackColor().colorWithAlphaComponent(0.64).CGColor     }      private func highlight() {         // ——— COMMENTING THIS MAKES THE BEACHBALL GO AWAY         backgroundLayer.backgroundColor = NSColor.grayColor().CGColor         textLayer.foregroundColor = NSColor.whiteColor().colorWithAlphaComponent(0.64).CGColor     }      // Tracking events     var isMouseDown = false      override func mouseDown(theEvent: NSEvent) {         super.mouseDown(theEvent)         isMouseDown = true         highlight()     }      override func mouseUp(theEvent: NSEvent) {         super.mouseUp(theEvent)         isMouseDown = false         normal()          if frame.contains(convertPoint(theEvent.locationInWindow, toView: self)) {             sendAction(action, to: target)         }     } } 

0 Answers

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment