This looks like a bug either in NSDocument or in SwiftUI’s bridge to NSDocument. Can you please file feedback with this sample code?
Oh I will.
Maybe not worth a whole new thread, but when I actually try this, I just get a warning:
(from Eliminate data races using Swift Concurrency - WWDC22 - Videos - Apple Developer)
Is there some stricter enforcement I need to turn on?
I don't think you can do this (easily) with async/await, but you should be able to with a callback-style API:
final class SlowDataModel {
private static func convert(_ text: String, on queue: DispatchQueue, group: DispatchGroup, completion: @escaping (String) -> Void) {
queue.async(group: group) {
sleep(10)
completion(text)
}
}
private var text: String!
private let group = DispatchGroup()
init(text: String) {
SlowDataModel.convert(text, on: /* some background queue */, group: self.group) { [weak self] (result) in
self?.text = result
}
}
var data: String {
// If the conversion has already finished, this should return instantly.
// Otherwise, blocks the thread.
group.wait()
// Since the conversion has finished, we know `text` cannot be nil
return text
}
}
That was essentially my first attempt
It seems to be the expected behavior and documented here in the Discussion part: performActivity(withSynchronousWaiting:using:) | Apple Developer Documentation
Of course the whole thing is highly customizable by subclassing NSDocument
. Not sure it's solvable with SwiftUI.
That’s why I suggested the bug might be in SwiftUI. The right folks will be able to review @audulus’s feedback.
For classes with internal locking mechanisms that ensure no races occur, you can mark it @unchecked Sendable
to make the compiler emit no warnings. I think the class still has to be final
though.
When trying the slow saving on iOS, there's a funny bug where when going back to the document browser, the document icon hovers over all the others as you scroll.