NSScrollView magnification with many subviews

I have a NSScrollView with many subviews ( greater than 100 ).


- The subviews are position constrained using autolayout to subview.center to edge of superview on horizontal/vertical axis.

- The subviews have dynamic internal content which can force the subview to grow or shrink as needed.


Scrolling works perfectly. Responsive scrolling is smooth and fast.


Magnification is horrible. Id be lucky if im getting 2-3 fps.


How can I optimise?

  • using can Draw Subviews Into Layer on parent and children.
  • hiding views.
  • using shouldRasterize.
  • removing subviews during magnify and replacing at end.
  • replacing the entire document view with a shadow proxy.




What I have noticed is that each frame seems to want an auto-layout pass which is what is sucking up the CPU. Yet the layout of the view doesnt go dirty during a magnify. As pointed out in the WWDC sessions auto-layout for siblings is roughly linear on count so it makes sense that magnification is smooth when the subview count is fairly small.


Any ideas


Thanks

Warren

Replies

What mechanism are you using for magnification?


One approach you can try is to modify the amount of scaling by changing only the documentView frame during the resizing gesture. (The "documentView" is NSScrollView's lingo for the scrollable content. There's an intermediate clipping view, whose property name is unfortunately "contentView", but that's not your content, but just a view into your content.)


When the documentView bounds are different in size from the documentView frame, there's automatic scaling of the content via a view transform. This should be fast, and not cause autolayout to run.


Then, at the end of the the resizing gesture, you can set the documentView bounds size to the size of the frame, which will reset the transform, and there should then be one iteration of layout.


The only complication is that (by default) changing a view frame automatically changes its bounds too. To prevent this, re-set the bounds first. That disables the automatic behavior, so you can change the frame and the bounds will be left alone.