Knowledge
Search knowledge... ⌘K
Knowledge · Guidelines · swift
Swift Appkit Crash Recovery Persistence
Crash-safe persistence for AppKit apps using debounced atomic writes to applicationSupportDirectory, applicationWillTerminate flush hook, and recovery-stamp behavior on load. Guarantees the user never loses more than a few hundred milliseconds of work even if the app is force-quit mid-session.
Metadata
swift swift mandatory
Procedures
Showing 3 of 6
- 1 Write to FileManager.applicationSupportDirectory, not Documents
```swift private static var persistenceFileURL: URL { let base = (try? FileManager.default.url( for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true )) ?? FileManager.default.homeDirectoryForCurrentUser .appendingPathComponent("Library/Application Support") let dir = base.appendingPathComponent("Whisperbar", isDirectory: true) if !FileManager.default.fileExists(atPath: dir.path) { try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) } return dir.appendingPathComponent("history.json") } ``` Application Support is sandbox-scoped, not Spotlight-indexed, and not user-visible in Finder by default — the right home for internal state. - 2 Use debounced writes (300ms) via DispatchWorkItem
```swift private var saveWorkItem: DispatchWorkItem? private func scheduleSave() { saveWorkItem?.cancel() let snapshot = self.history // capture by value let item = DispatchWorkItem { let url = Self.persistenceFileURL do { let encoder = JSONEncoder() encoder.dateEncodingStrategy = .iso8601 encoder.outputFormatting = [.prettyPrinted, .sortedKeys] let data = try encoder.encode(snapshot) try data.write(to: url, options: .atomic) } catch { /* log metadata only */ } } saveWorkItem = item DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + 0.3, execute: item) } ``` `.atomic` write is critical — it writes to a temp file and renames, so the file is never partially written on crash. - 3 Expose flushNow() that cancels the pending work item and runs it synchronously
```swift func flushNow() { saveWorkItem?.cancel() let snapshot = self.history // Run synchronously on calling queue: // (implementation of the write block — same as in scheduleSave) performSaveSync(snapshot) } ```