3

I am trying to understand its usage better in order to improve scrolling performance on OSX. More specifically, I am trying to eradicate the "flashing/flickering" on the side of the screen as you scroll fast and AppKit runs into non-overdrawn (non-prepared) portions of your view OR portions of your view that have been prepared incorrectly with background-only.

My understanding is that the preparedContentRect represents the overdrawn section of your scrollview - the area available for responsive scrolling.

Part One

I placed code within the preparedContentInRect for two subViews of NSScrollView - each are floating subViews of NSScrollView which behave the same as documentViews when scrolling.

The preparedContentInRect gets called several times just after program launch (as expected). I then scroll to the end of the prepared area BUT (unexpectedly) it doesn't get called again as I get nearer and nearer and even on the edge of the prepared area. Why not? Even with no user interaction with the UI (system idle) it does not call preparedContentInRect to enlarge the overdraw area dynamically.

Part Two

Since (as above) I could not rely on AppKit calling preparedContentInRect when needed; I reorganised my code to prepare the preparedContentRect after each notification from the clipview's boundsChangeNotification and then call prepareContentInRect manually to inform AppKit of the new overdraw area.

I have included a "manual" flag so that my custom override can differentiate between my manual calls to prepareContentInRect and internal calls from AppKit - so as not to let AppKit mess up the overdraw!!!

var manuallyPrepareContentInRect = false
override func prepareContentInRect(rect: NSRect) {
    if manuallyPrepareContentInRect{
        println("GRID manual prepareContentInRect call: \(rect)")
        manuallyPrepareContentInRect = false
        super.prepareContentInRect(rect)
        return
    }
    println("GRID bypass AppKit prepareContentInRect call: \(self.preparedContentRect)")
    super.prepareContentInRect(self.preparedContentRect)
}

Unfortunately, even though prepareContentRect is reporting my intended prepare rect, when it scrolls it does not seem to have prepared the rect as I have intended - it prepares a rect 3,500 points wide instead of 5,040 wide and hence I run into the dreaded background color while waiting for the rest of the view to render.

The only "special" thing about the view that isn't getting correct overdraw is that it has a whole lot of subviews that have been drawn into its layer using canDrawSubviewsIntoLayer.

What am I misunderstanding above with respect to prepareContentInRect and overdraw? Why is AppKit behaving like it is?

Sam
  • 2,745
  • 3
  • 20
  • 42
  • In part one, are the views actually subviews of a document view, which is itself the subview of a clip view? Do you get the behavior you expect from AppKit in a simpler setup, overriding prepareContentInRect in a document view? – Adam Preble Mar 26 '15 at 13:30
  • @AdamPreble No they are not actually subViews of the documentView. Using a newish API on NSScrollView from around 10.9+ called `floatingSubViews`. These views are direct children of the NSScrollView and are effectively docked to the top and left of my scrollView respectively. – Sam Mar 26 '15 at 13:42
  • @AdamPreble However, they do scroll 100% in sync with the documentView. (I have checked a frame by frame replay.) – Sam Mar 26 '15 at 13:43
  • Checked a direct child of the documentView - same behaviour. `prepareContentInRect` triggered on resize & minimise but not general (do nothing and stare at the screen) idle. – Sam Mar 26 '15 at 13:57

0 Answers0