NotificationCenter Crash On iOS 18+ Swift6.2

After switching our iOS app project from Swift 5 to Swift 6 and publishing an update, we started seeing a large number of crashes in Firebase Crashlytics.

The crashes are triggered by NotificationCenter methods (post, addObserver, removeObserver) and show the following error:

BUG IN CLIENT OF LIBDISPATCH: Assertion failed: Block was expected to execute on queue [com.apple.main-thread (0x1f9dc1580)]

All scopes to related calls are already explicitly marked with @MainActor. This issue never occurred with Swift 5, but appeared immediately after moving to Swift 6.

Has anyone else encountered this problem? Is there a known solution or workaround?

Thanks in advance!

Answered by DTS Engineer in 866121022

The Swift 6 language mode enables some main-actor checking [1] and you’re probably hitting that. This is a good thing, because previously you were just running main thread code off the main thread, and that can produce all sorts of problems that are much harder to debug.

It’s hard to offer specific advice without seeing the code that’s failing. Can you reproduce this in your office? If so, create a small test project that shows the issue and then post some snippets from that and a corresponding Apple crash report (see Posting a Crash Report for advice on how to get and post that).

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] See SE-0423

Accepted Answer

The Swift 6 language mode enables some main-actor checking [1] and you’re probably hitting that. This is a good thing, because previously you were just running main thread code off the main thread, and that can produce all sorts of problems that are much harder to debug.

It’s hard to offer specific advice without seeing the code that’s failing. Can you reproduce this in your office? If so, create a small test project that shows the issue and then post some snippets from that and a corresponding Apple crash report (see Posting a Crash Report for advice on how to get and post that).

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] See SE-0423

You were right. We've found out that the issue was that we registered an observer with addObserver using a #selector that pointed to a function marked as @MainActor, but we were calling the NotificationCenter.post method from a background thread. Apparently this caused the main-actor isolation check to fail, which led to a crash.

Even though there is no data-race or UI operation in the function, looks like it is enough for the function to be @MainActor to cause a crash when called from outside the main thread.

We fixed it by making sure the relevant NotificationCenter.post calls are executed on the main thread.

Initially, we thought that marking the function with @MainActor would prevent it from being called from a nonisolated context by producing a compile-time error in Swift 6 mode. But since a Selector instance is not aware of the actor isolation of the target function, Xcode is not able to show a warning and it caused us to not realize the issue at first.

I appreciate your guidance @DTS Engineer.

NotificationCenter Crash On iOS 18+ Swift6.2
 
 
Q