From bef29a79a88477e5465bbe1d228deb75dc627cb7 Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Wed, 24 Jun 2026 18:52:32 +0200 Subject: [PATCH] Keep Sparkle resetUpdateCycle on the main actor SPUUpdater is a main-thread-only API; calling resetUpdateCycle() from a detached utility task violated Sparkle's threading contract and raised a Swift 6 concurrency error (non-Sendable SPUUpdater captured in a detached task). A plain main-actor Task keeps the deferral that avoids running the feed-cache work synchronously inside the didSet. --- Yattee/Services/Updates/SparkleUpdater.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Yattee/Services/Updates/SparkleUpdater.swift b/Yattee/Services/Updates/SparkleUpdater.swift index 5d6272e5..cb66d60a 100644 --- a/Yattee/Services/Updates/SparkleUpdater.swift +++ b/Yattee/Services/Updates/SparkleUpdater.swift @@ -33,12 +33,12 @@ final class AppUpdater { didSet { guard oldValue != wantsBetaChannel else { return } UserDefaults.standard.set(wantsBetaChannel, forKey: Self.wantsBetaKey) - // Trigger re-check so the delegate re-reads channels. Deferred off - // the main thread — resetUpdateCycle may synchronously touch the - // scheduler's feed cache which can stutter SwiftUI scrolling. - let updater = self.updaterController.updater - Task.detached(priority: .utility) { - updater.resetUpdateCycle() + // Trigger re-check so the delegate re-reads channels. Deferred to + // a later main-actor turn so the feed-cache work doesn't run + // synchronously inside this didSet (which can stutter SwiftUI + // scrolling). Must stay on main: SPUUpdater is main-thread-only. + Task { @MainActor in + self.updaterController.updater.resetUpdateCycle() } } }