cocoa - Why is an empty drawRect interfering with a simple animation? -


i'm trying put own take on cocoa's nspathcontrol.

enter image description here

in bid figure out best way handle expand-contract animation when mouse on component in control, put simple sample app. things going - mouse or out of view containing path components , you'd simple animation using following code:

// code belongs pathview (not pathcomponentview)  override func mouseentered(theevent: nsevent) {      nsanimationcontext.runanimationgroup({ (ctx) -> void in         self.animatetoproportions([cgfloat](arrayliteral: 0.05, 0.45, 0.45, 0.05))     }, completionhandler: { () -> void in             //     }) }  // animating subviews  func animatetoproportions(proportions: [cgfloat]) {      let height = self.bounds.height     let width = self.bounds.width      var xoffset: cgfloat = 0     (i, proportion) in enumerate(proportions) {         let subview = self.subviews[i] as! nsview         let newframe = cgrect(x: xoffset, y: 0, width: width * proportion, height: height)         subview.animator().frame = newframe         xoffset = subview.frame.maxx     } } 

as next step in control's development, instead of using nsview instances path components started using own nsview subclass:

class pathcomponentview: nsview {      override func drawrect(dirtyrect: nsrect) {         super.drawrect(dirtyrect)     } } 

although identical nsview, when use class in animation, animation no longer it's supposed - frames set subviews pretty ignored, , whole effect ugly. if comment out drawrect: method of subclass things return normal. can explain what's going wrong? why presence of drawrect: interfering animation?

i've put demo project on github page.

you've broken rules here, , when break rules, behavior becomes undefined.

in layer backed view, must not modify layer directly. see documentation wantslayer (which how specify it's layer-backed):

in layer-backed view, drawing done view cached underlying layer object. cached content can manipulated in ways more performant redrawing view contents explicitly. appkit automatically creates underlying layer object (using makebackinglayer method) , handles caching of view’s content. if wantsupdatelayer method returns no, should not interact underlying layer object directly. instead, use methods of class make changes view , layer. if wantsupdatelayer returns yes, acceptable (and appropriate) modify layer in view’s updatelayer method.

you make call:

subview.layer?.backgroundcolor = color.cgcolor 

that's "interact[ing] underlying layer object directly." you're not allowed that. when there's no drawrect, appkit skips trying redraw view , uses core animation animate what's there, gives expect (you're getting lucky there; it's not promised work).

but when sees implemented drawrect (it knows did, doesn't know what's inside), has call perform custom drawing. it's responsibility make sure drawrect fills in every pixel of rectangle. can't rely on backing layer (that's cache). draw nothing, you're seeing default background gray intermixed cached color. there's no promise of pixels updated correctly once we've gone down road.

if want manipulate layer, want "layer-hosting view" not "layer-backed view." can replacing appkit's cache layer own custom layer.

let subview = showmetheproblem ? pathcomponentview() : nsview() addsubview(subview) subview.layer = calayer() // use our layer, not appkit's caching layer. subview.layer?.backgroundcolor = color.cgcolor 

while doesn't matter in case, keep in mind layer-backed view , layer-hosting view have different performance characteristics. in layer-backed view, appkit caching drawrect results caching layer, , applying animations on automatically (this allows existing appkit code written before calayer nice opt-in performance improvements without changing much). in layer-hosting view, system more ios. don't magical caching. there's layer, , can use core animation on it.


Comments

Popular posts from this blog

php - Wordpress website dashboard page or post editor content is not showing but front end data is showing properly -

How to get the ip address of VM and use it to configure SSH connection dynamically in Ansible -

javascript - Get parameter of GET request -