Keeping PDF Loading Off the Main Actor
The first hardening pass fixed a problem users would feel before they could hear a single word: waiting for a document to open.
The problem
PDF text extraction is local work, but a large document can still take enough time to make a SwiftUI screen feel stuck. A second problem shows up when a reader leaves while a load is still running: old text can arrive after the screen has moved on.
// Before: synchronous work tied to the view task
let text = try DocumentTextLoader.load(from: url, kind: document.kind)
self.text = text
The change
I moved DocumentTextLoader behind a small Swift actor. The reader now awaits the result and checks cancellation before publishing it to the view. That keeps extraction away from the main actor and stops a cancelled load from replacing the current document.
// After: isolate the loader and ignore cancelled work
actor DocumentTextLoader {
static let shared = DocumentTextLoader()
func load(from url: URL, kind: DocumentKind) throws -> String { ... }
}
let loadedText = try await DocumentTextLoader.shared.load(from: url, kind: kind)
try Task.checkCancellation()
text = loadedText
Result
The UI has one clear loading path, and the reader only displays text that belongs to the active document. This is a small change, but it removes a class of timing bugs without adding another dependency.