title: How do I prevent Cocoa from calling drawRect on every completely invisible sub-view
body: <p>I have a completely working, very fast, single window app, written in Objective-C and originally developed on MacOS 10.7 using XCode 4.  It has a single scroll view showing portions of one large content view with many sub-views.  Only a portion of each sub-view shows, and only that sub-view that is initially visible gets its <code>-drawRect</code> method called when the app shows the initial window.  The content view being scrolled and all of its sub-views and sub-sub-views are created programmatically when the app launches (not from the xib file).</p>
  
  <p>Each sub-view usually has a variety of controls and one special sub-classed sub-sub-view that displays a computationally intensive drawing that gets precomputed and cached the first time its <code>-drawRect</code> method is called.  So scrolling through all this distributes the computation and caching until just when the user needs to see it.  This all works well and has done so for years.  None of the sub-sub-views' <code>-drawRect</code> methods is ever called until the sub-sub-view has a portion of itself that becomes visible within the hierarchy during scrolling.</p>
  
  <p>The problem is that I've now ported the app to XCode 9.3 and MacOS 10.13.4, and have discovered that after the single window with the scrolling view in it is shown for the first time at launch on the desktop, every sub-sub-view is having its <code>-drawRect</code> method called by Cocoa's runtime, even though <em>none</em> of the sub-sub-views are even spatially close to being visible in the view hierarchy inside the scrolling view in the window.  This causes every one of the sub-sub-views to pre-compute and cache, all before the user can interact with the just-launched app.  This takes many seconds, which is unacceptable user-interface-wise.</p>
  
  <p>I have no idea what my unchanged code might be doing to cause all the invisible sub-sub-views to be asked to draw themselves, and so it seems this new state of affairs could be due to some later Apple framework behavior changes.  I've tried querying the <code>-isHiddenOrHasHiddenAncestor</code> property of the sub-sub-view inside <code>-drawRect</code>, but it is always returning false, probably because the super-views are logically visible but being clipped by the scrolling view.</p>
  
  <p>How does one debug this situation, which seems completely contrary to what the view system is supposed to be doing automatically?  Under what circumstances does the system call a view's <code>-drawRect</code> when the view's frame is completely unable to show anything?  Did something change on Apple's framework side?</p>