title: iOS9 This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes
body: <p>I have just dowloaded the latest XCode (7.1 beta) and have started playing around with iOS9.</p>
  
  <p>I had an app working perfectly with no errors in iOS8 but now I get the following error from overriding the drawRect method in a UITableViewCell class :</p>
  
  <p>"This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes.  This will cause an exception in a future release."</p>
  
  <p>here is the backtrace : </p>
  
  <pre><code>Stack:(
  0   CoreFoundation                      0x000000010a749f65 __exceptionPreprocess + 165
  1   libobjc.A.dylib                     0x0000000109dcfdeb objc_exception_throw + 48
  2   CoreFoundation                      0x000000010a749e9d +[NSException raise:format:] + 205
  3   Foundation                          0x0000000109b442e5 _AssertAutolayoutOnMainThreadOnly + 79
  4   Foundation                          0x00000001099a4ece -[NSISEngine withBehaviors:performModifications:] + 31
  5   UIKit                               0x000000010b9d425b -[UIView(AdditionalLayoutSupport) _withAutomaticEngineOptimizationDisabledIfEngineExists:] + 58
  6   UIKit                               0x000000010b9d4d9e -[UIView(AdditionalLayoutSupport) updateConstraintsIfNeeded] + 254
  7   UIKit                               0x000000010b702760 -[UITableViewCellContentView updateConstraintsIfNeeded] + 185
  8   UIKit                               0x000000010b9d5ab3 -[UIView(AdditionalLayoutSupport) _updateConstraintsAtEngineLevelIfNeeded] + 272
  9   UIKit                               0x000000010b1e6274 -[UIView(Hierarchy) _updateConstraintsAsNecessaryAndApplyLayoutFromEngine] + 159
  10  UIKit                               0x000000010b1f5d84 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 710
  11  QuartzCore                          0x000000010ae1059a -[CALayer layoutSublayers] + 146
  12  QuartzCore                          0x000000010ae04e70 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
  13  QuartzCore                          0x000000010ae04cee _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
  14  QuartzCore                          0x000000010adf9475 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 277
  15  QuartzCore                          0x000000010ae26c0a _ZN2CA11Transaction6commitEv + 486
  16  QuartzCore                          0x000000010ae2737c _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 92
  17  CoreFoundation                      0x000000010a675967 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
  18  CoreFoundation                      0x000000010a6758d7 __CFRunLoopDoObservers + 391
  19  CoreFoundation                      0x000000010a66ae4c CFRunLoopRunSpecific + 524
  20  CoreFoundation                      0x000000010a71e011 CFRunLoopRun + 97
  21  SDWebImage                          0x000000010971773c -[SDWebImageDownloaderOperation start] + 1868
  22  Foundation                          0x0000000109961e47 __NSOQSchedule_f + 194
  23  libdispatch.dylib                   0x000000010d93849b _dispatch_client_callout + 8
  24  libdispatch.dylib                   0x000000010d91e8ec _dispatch_queue_drain + 2215
  25  libdispatch.dylib                   0x000000010d91de0d _dispatch_queue_invoke + 601
  26  libdispatch.dylib                   0x000000010d920a56 _dispatch_root_queue_drain + 1420
  27  libdispatch.dylib                   0x000000010d9204c5 _dispatch_worker_thread3 + 111
  28  libsystem_pthread.dylib             0x000000010dc80a9d _pthread_wqthread + 729
  29  libsystem_pthread.dylib             0x000000010dc7e3dd start_wqthread + 13
  )
  </code></pre>
  
  <p>Here is the drawRect Method :</p>
  
  <pre><code>override func drawRect(rect: CGRect) {
  
      super.drawRect(rect)
  
      let cellRect = rect
  
      // Values
      let buttonBoxX = CELL_MARGIN + CELL_MARGIN/2
      let buttonBoxY = cellRect.height - buttonBoxHeight
      let buttonBoxWidth = rect.width - CELL_MARGIN * 3
  
  
      // Set Button Box
      let buttonBoxRect = CGRectMake(buttonBoxX, buttonBoxY, buttonBoxWidth, buttonBoxHeight )
      let buttonBox = UIBezierPath(roundedRect: buttonBoxRect, byRoundingCorners: [.BottomRight, .BottomLeft], cornerRadii: CGSize(width: CORNER_RADIUS, height: CORNER_RADIUS)) // Create the path
      UIColor.whiteColor().setFill() // Set the Fill to be white
  
      buttonBox.fill()
  
  
  }
  </code></pre>
  
  <p>My understanding (cf. <a href="https://stackoverflow.com/questions/31951704/this-application-is-modifying-the-autolayout-engine-from-a-background-thread-wh">this question</a>) is that complicated calculations etc should be done on a background thread and the the update of the UI on the main thread because UI is not thread safe.</p>
  
  <p>However, IF i use the following : </p>
  
  <pre><code>override func drawRect(rect: CGRect) {
  
      super.drawRect(rect)
  
      let cellRect = rect
  
      // Values
      let buttonBoxX = CELL_MARGIN + CELL_MARGIN/2
      let buttonBoxY = cellRect.height - buttonBoxHeight
      let buttonBoxWidth = rect.width - CELL_MARGIN * 3
  
  
      // Set Button Box
      let buttonBoxRect = CGRectMake(buttonBoxX, buttonBoxY, buttonBoxWidth, buttonBoxHeight )
      let buttonBox = UIBezierPath(roundedRect: buttonBoxRect, byRoundingCorners: [.BottomRight, .BottomLeft], cornerRadii: CGSize(width: CORNER_RADIUS, height: CORNER_RADIUS)) // Create the path
      UIColor.whiteColor().setFill() // Set the Fill to be white
  
      dispatch_async(dispatch_get_main_queue(), {
          buttonBox.fill()
      })
  
  
  }
  </code></pre>
  
  <p>I now get a CGContext error…</p>
  
  <pre><code>&lt;Error&gt;: CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
  &lt;Error&gt;: CGContextSetFlatness: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
  &lt;Error&gt;: CGContextAddPath: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
  &lt;Error&gt;: CGContextDrawPath: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
  &lt;Error&gt;: CGContextRestoreGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
  &lt;Error&gt;: CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
  &lt;Error&gt;: CGContextSetFlatness: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
  &lt;Error&gt;: CGContextAddPath: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
  &lt;Error&gt;: CGContextDrawPath: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
  &lt;Error&gt;: CGContextRestoreGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
  </code></pre>
  
  <p>Any suggestions ?</p>
  
  <p>SOLUTION : 
  OK. here is the deal. I was loading an image into a UIImageView asynchronously, but not "painting" it in the UI on the main thread but on a background thread. Furthermore; I was calling setNeedsDisplay on the UITableViewCell after adding the image to the UI, thus calling the drawRect method again… but this time on the background thread. </p>