From 4e26f9943b7e6d7d682d478e2324912aabb6d2db Mon Sep 17 00:00:00 2001 From: Mariusz Klochowicz Date: Tue, 25 Nov 2025 16:17:06 +1030 Subject: [PATCH] refactor(apple): remove unsafe code instance (#10967) Use the Combine pattern to avoid unsafe code. --- .../Views/UpdateNotification.swift | 35 ++++++------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/UpdateNotification.swift b/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/UpdateNotification.swift index 2eae95242..b8993e9c3 100644 --- a/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/UpdateNotification.swift +++ b/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/UpdateNotification.swift @@ -23,11 +23,7 @@ } } - // nonisolated(unsafe) is required because: - // 1. Timer.invalidate() is thread-safe and can be called from any thread - // 2. Only accessed from MainActor-isolated methods (init, start/stop) and nonisolated deinit - // 3. deinit is nonisolated and needs access to invalidate the timer - private nonisolated(unsafe) var timer: Timer? + private var timerCancellable: AnyCancellable? private let notificationAdapter: NotificationAdapter = NotificationAdapter() private let versionCheckUrl: URL private let marketingVersion: SemanticVersion @@ -53,29 +49,20 @@ } private func startCheckingForUpdates() { - guard timer == nil else { return } - - self.timer = Timer.scheduledTimer( - timeInterval: 6 * 60 * 60, - target: self, - selector: #selector(checkForUpdates), - userInfo: nil, - repeats: true - ) + guard timerCancellable == nil else { return } + // Check immediately checkForUpdates() + + // Then check every 6 hours + timerCancellable = Timer.publish(every: 6 * 60 * 60, on: .main, in: .default) + .autoconnect() + .sink { [weak self] _ in + self?.checkForUpdates() + } } - private func stopCheckingForUpdates() { - timer?.invalidate() - self.timer = nil - } - - deinit { - timer?.invalidate() - } - - @objc private func checkForUpdates() { + private func checkForUpdates() { if configuration.disableUpdateCheck { return }