qwerty_so
qwerty_so

Reputation: 36305

Drawing in NSView from background operation has no effect

I'm trying to draw to a NSView from a background operation, but don't see any effect.

let queue = OperationQueue()
queue.addOperation() {
  doTheBackgroundStuff()
}

starts the background operation, which is doing lots of calculations. In the AppDelegate I have

@IBOutlet weak var image: NSImageView!  // some image to show
@IBOutlet weak var number: NSTextField! // a corresponding number
@IBOutlet weak var mainView: NSView!    // the main view holding the above

The assignment

number.intValue = Int32(someNumber)

is issued from the background operation regularly (often). But the text does never change. I have set the "can draw concurrently" in IB for the view as well as for the TextField. I also tried

if mainView.lockFocusIfCanDraw() {
  mainView.setNeedsDisplay(mainView.rectPreservedDuringLiveResize)
  mainView.unlockFocus()
}

after the text field assignment. Also to no avail.

Upvotes: 4

Views: 697

Answers (2)

sas
sas

Reputation: 7542

Typically these problems go away if you send your view updating code back to the main queue from within your background task:

DispatchQueue.main.async {
    // your view update code
}

If there's not too many place inside your doTheBackgroundStuff you could just sprinkle those in for view updates, i.e. whenever you access your mainView.

Otherwise it helps to re-group things into parts that do non-UI heavy lifting and then push the view updates to Dispatch.main.async at the end.

Upvotes: 2

PDK
PDK

Reputation: 1536

Call flushGraphics as described in https://stackoverflow.com/a/19997698/3419541:

I read about NSGraphicsContext Restriction at Thread guide.

Here, I found the following line:

If you do any drawing from a secondary thread, you must flush your drawing calls manually. Cocoa does not automatically update views with content drawn from secondary threads, so you need to call the flushGraphics method of NSGraphicsContext when you finish your drawing. If your application draws content from the main thread only, you do not need to flush your drawing calls.

Upvotes: 3

Related Questions