perf: move SwiftData cache and JSON encode off main thread during sync
- cacheStories() runs in Task.detached with a background ModelContext - persistQuickCache() encodes 100 stories off-thread via Task.detached - loadSectionSupplements() batches 5 parallel fetches into one sectionSupplement write Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -45,12 +45,16 @@ final class StoryStore: ObservableObject {
|
||||
}
|
||||
|
||||
/// Persist the current feed to UserDefaults so it survives process kills.
|
||||
/// Encoding runs off the main thread; UserDefaults.set is thread-safe.
|
||||
private func persistQuickCache() {
|
||||
let encoder = JSONEncoder()
|
||||
encoder.dateEncodingStrategy = .iso8601
|
||||
let payload = QuickCachePayload(stories: Array(stories.prefix(100)), savedAt: Date())
|
||||
if let data = try? encoder.encode(payload) {
|
||||
UserDefaults.standard.set(data, forKey: quickCacheKey)
|
||||
let key = quickCacheKey
|
||||
Task.detached {
|
||||
let encoder = JSONEncoder()
|
||||
encoder.dateEncodingStrategy = .iso8601
|
||||
if let data = try? encoder.encode(payload) {
|
||||
UserDefaults.standard.set(data, forKey: key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,15 +223,24 @@ final class StoryStore: ObservableObject {
|
||||
|
||||
func loadSectionSupplements() {
|
||||
guard selectedTags.isEmpty else { return } // only for "All" pill
|
||||
for sec in supplementSections {
|
||||
let id = sec.id
|
||||
let tags = sec.tags
|
||||
Task { [weak self] in
|
||||
guard let self else { return }
|
||||
if let result = try? await api.fetchStories(tags: tags, limit: 8) {
|
||||
await MainActor.run { self.sectionSupplement[id] = result.data }
|
||||
let sections = supplementSections
|
||||
Task { [weak self] in
|
||||
guard let self else { return }
|
||||
var merged: [String: [StorySummary]] = [:]
|
||||
await withTaskGroup(of: (String, [StorySummary]?).self) { group in
|
||||
for sec in sections {
|
||||
let id = sec.id
|
||||
let tags = sec.tags
|
||||
group.addTask {
|
||||
let result = try? await APIClient.shared.fetchStories(tags: tags, limit: 8)
|
||||
return (id, result?.data)
|
||||
}
|
||||
}
|
||||
for await (id, data) in group {
|
||||
if let data { merged[id] = data }
|
||||
}
|
||||
}
|
||||
self.sectionSupplement = merged // single main-thread update
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user