I'm seeing the same behavior and have the same question. I'm using Xcode 12.1. Does anybody know why this occurs?
Post
Replies
Boosts
Views
Activity
We are using async. If I have an object that has a load() async method and a .loadStatus property (values might be something like not-loaded, loading, loaded), and the .load() can be called from and completed on an arbitrary thread (it might make a network request let's say). I like the pattern of our properties that can change being @Published as a built-in property wrapper for this situation. However, in our case where the method can complete on any given thread you end up with a bug like this:
foo.load()
XCTAssertEquals(foo.loadStatus, .loaded)
This fails, loadStatus is "loading" because it's Published and I have to DispatchQueue.main.async the load status update to avoid purple runtime errors.
Nevermind. We had this class embedded in a function. Removing the definition out of that scope solved it.
Actually, when building with strict-concurrency=complete and Xcode 14.3 I am seeing these errors again. ASPresentationAnchor() is MainActor, so it seems impossible to implement ASWebAuthenticationPresentationContextProviding and return a ASPresentationAnchor.
Actually, my logging wasn't working as I thought it was. I'm still not seeing UIApplication.willTerminateNotification which might be intended, but I am seeing the relaunch work with exit now that I've fixed the logging.
I no longer have a need for this. I misunderstood the worldAlignment property. Now that I understand it, I don't need this specific question answered
Thanks Quinn. I can also work around the bug by using for in instead of .forEach:
...
init(store: MyStore) async throws {
for persisted in try await store.persisted {
credentials.append(persisted)
}
}
So I think it has something to do with Actor inference in the .forEach closure.
I filed a bug with Swift: https://github.com/swiftlang/swift/issues/76804
MyController is a simple class not bound to any actor. The init code is above, it is also not bound to any actor.
I tried binding the init to the MainActor, that didn't help.
I also tried making the closures passed into progress @Sendable and that did not fix it, which surprised me.
I've got the same basic project that I extracted to try to get a reproducer. I also setup unit tests with both Swift Testing and XCTest (we mostly see this issue in our test environment). Unfortunately, I have not been able to reproduce it outside of our codebase.
Our code is in a Swift Package, so one thing that I haven't tried is breaking out this reproducible code into a package and making that package a dependency of an app. There is no practical difference I can identify between the code we have tried to reproduce the crash and our production code.
Within our production codebase, I can reproduce with this simple class:
public final class MyController {
public let progress: Progress
init() {
progress = Progress()
progress.cancellationHandler = {}
}
}
And this simple test:
import Testing
@Test
func reproDispatchAssertQueueFail() async throws {
let dc = MyController()
dc.progress.cancel()
}
In this case, MyController is defined in a Package, which the test imports. I cannot reproduce this when MyController is defined in the same file as the test.
Pulling that same code into a brand new sample project, I cannot reproduce this.
Also, I do not see this issue when testing against iOS 17.5, I'm only seeing it on iOS 18 simulators.
Also, it readily reproduces after running the test immediately after a clean and rebuild of the package defining MyController.
Interestingly enough, I just ran our test against Mac Catalyst and it doesn't crash, but I get a purple runtime warning:
warning: data race detected: @MainActor function at MyController.swift:8 was not called on the main thread
I’d like to confirm two things:
You’re testing this from Xcode 16.0.
Targeting the iOS 18.0 simulator.
Yes on both.
First, add this your code:
The Test.counter line generates this error:
Main actor-isolated static property 'counter' can not be mutated from a nonisolated context
Second, tweak your setup like this:
progress.cancellationHandler = { @Sendable in }
Unfortunately, that does not prevent the trap, no.
Thanks for your help.
Crash report attached.
xctest-2024-10-09-091718.txt
I have a reproducible project. I zipped it up but I can't seem to attach a zip file. It's only 91KB
FB15511118