PKBeam
PKBeam

Reputation: 159

What's causing this? - "CoreAnimation: warning, deleted thread with uncommitted CATransaction"

Xcode 8.2.1 / macOS 10.12.4 beta

I'm trying to understand an error I'm getting:

CoreAnimation: warning, deleted thread with uncommitted CATransaction; set CA_DEBUG_TRANSACTIONS=1 in environment to log backtraces, or set CA_ASSERT_MAIN_THREAD_TRANSACTIONS=1 to abort when an implicit transaction isn't created on a main thread.

I have a block of code in a swift file that sends a network request, retrieves some data and processes it before posting a notification:

// global variable
var data: [String: Any] = [:]

func requestData() {
    ...
    do {
        // process data              
        data = processedData                        
        NotificationCenter.default.post(name: didProcessData, object: nil)
        }
    } catch {
        ...
    }

In my main ViewController.swift file, an observer listens for the notification and updates the view.

func updateView() {
    // update the view
    textField.stringValue = "..."
}

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(updateView), name: didProcessData, object: nil)

}

When updateView() is called, the actual text fields and such take a random amount of time to actually update, and the aforementioned error appears.

My guess was that there was an issue with thread safety, so I changed updateView() like so:

func updateView() {
    DispatchQueue.main.async(execute: {
        // update the view
        self.textField.stringValue = "..."
    })
}

And now the view updates properly. But I'm still relatively inexperienced with programming, and I don't quite understand what exactly is causing the error.

Upvotes: 1

Views: 1384

Answers (1)

Andreas Oetjen
Andreas Oetjen

Reputation: 10209

Your notification handler (updateView) is called from an arbitrary thread -- e.g. not from the main thread (so-called UI-Thread). Several framework APIs detect when they are called from outside the main thread (as a kind-of warning).

If you want to update the UI, you'll have to make sure that this code is executed in the main thread; this is typically accomplished by enqueuing a closure (work item) to DispatchQueue.main.async, which is part of GCD (Grand Central Dispatch).

Upvotes: 1

Related Questions