From 58e375ec417aa2c604eac7c6e8548f1cd700e6f3 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Fri, 15 Jul 2022 17:21:40 +0200 Subject: [PATCH] Attach @MainActor where needed Some methods were updating UI from non-main thread. --- .../App/Intents/IntentDispatcher+Activities.swift | 1 + Passepartout/App/Intents/IntentsManager.swift | 4 +++- Passepartout/App/Views/AddProviderViewModel.swift | 2 ++ Passepartout/AppShared/Context/CoreContext+Shared.swift | 2 ++ Passepartout/AppShared/Context/CoreContext.swift | 1 + .../Managers/DefaultProfileManager.swift | 8 +++++--- .../Sources/PassepartoutUtils/Reusable/SSIDReader.swift | 6 ++++-- .../PassepartoutVPN/Managers/MockVPNManagerStrategy.swift | 3 +++ .../Managers/TunnelKitVPNManagerStrategy.swift | 4 +++- 9 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Passepartout/App/Intents/IntentDispatcher+Activities.swift b/Passepartout/App/Intents/IntentDispatcher+Activities.swift index 246fd49f..9e88660e 100644 --- a/Passepartout/App/Intents/IntentDispatcher+Activities.swift +++ b/Passepartout/App/Intents/IntentDispatcher+Activities.swift @@ -27,6 +27,7 @@ import Foundation import Intents import PassepartoutLibrary +@MainActor extension IntentDispatcher { private enum IntentError: Error { case notProvider(UUID) diff --git a/Passepartout/App/Intents/IntentsManager.swift b/Passepartout/App/Intents/IntentsManager.swift index 15387c85..22f9a243 100644 --- a/Passepartout/App/Intents/IntentsManager.swift +++ b/Passepartout/App/Intents/IntentsManager.swift @@ -93,7 +93,9 @@ extension IntentsManager: INUIEditVoiceShortcutViewControllerDelegate { // so damn it, reload manually after a delay Task { await Task.maybeWait(forMilliseconds: Constants.Delays.xxxReloadEditedShortcut) - reloadShortcuts() + await MainActor.run { + reloadShortcuts() + } } } diff --git a/Passepartout/App/Views/AddProviderViewModel.swift b/Passepartout/App/Views/AddProviderViewModel.swift index 848b9e74..7ea83630 100644 --- a/Passepartout/App/Views/AddProviderViewModel.swift +++ b/Passepartout/App/Views/AddProviderViewModel.swift @@ -27,6 +27,8 @@ import Foundation import PassepartoutLibrary extension AddProviderView { + + @MainActor class ViewModel: ObservableObject { enum PendingOperation { case index diff --git a/Passepartout/AppShared/Context/CoreContext+Shared.swift b/Passepartout/AppShared/Context/CoreContext+Shared.swift index 88b5ddef..5f41ed78 100644 --- a/Passepartout/AppShared/Context/CoreContext+Shared.swift +++ b/Passepartout/AppShared/Context/CoreContext+Shared.swift @@ -27,6 +27,8 @@ import Foundation import PassepartoutLibrary extension CoreContext { + + @MainActor static let shared = CoreContext(store: UserDefaultsStore(defaults: .standard)) } diff --git a/Passepartout/AppShared/Context/CoreContext.swift b/Passepartout/AppShared/Context/CoreContext.swift index 27555a6a..91867459 100644 --- a/Passepartout/AppShared/Context/CoreContext.swift +++ b/Passepartout/AppShared/Context/CoreContext.swift @@ -60,6 +60,7 @@ class CoreContext { private var cancellables: Set = [] + @MainActor init(store: KeyValueStore) { self.store = store diff --git a/PassepartoutLibrary/Sources/PassepartoutProfiles/Managers/DefaultProfileManager.swift b/PassepartoutLibrary/Sources/PassepartoutProfiles/Managers/DefaultProfileManager.swift index 7054368b..c7a92e92 100644 --- a/PassepartoutLibrary/Sources/PassepartoutProfiles/Managers/DefaultProfileManager.swift +++ b/PassepartoutLibrary/Sources/PassepartoutProfiles/Managers/DefaultProfileManager.swift @@ -288,8 +288,10 @@ extension DefaultProfileManager { currentProfile.isLoading = true Task { try await makeProfileReady(profile) - currentProfile.value = profile - currentProfile.isLoading = false + await MainActor.run { + currentProfile.value = profile + currentProfile.isLoading = false + } } } } @@ -334,7 +336,7 @@ extension DefaultProfileManager { didUpdateProfiles.send() - // IMPORTANT: defer task to avoid recursive saves + // IMPORTANT: defer task to avoid recursive saves (is non-main thread an issue?) // FIXME: Core Data, not sure about this workaround Task { fixDuplicateNames(in: newHeaders) diff --git a/PassepartoutLibrary/Sources/PassepartoutUtils/Reusable/SSIDReader.swift b/PassepartoutLibrary/Sources/PassepartoutUtils/Reusable/SSIDReader.swift index 1e12c546..7a411b9d 100644 --- a/PassepartoutLibrary/Sources/PassepartoutUtils/Reusable/SSIDReader.swift +++ b/PassepartoutLibrary/Sources/PassepartoutUtils/Reusable/SSIDReader.swift @@ -53,8 +53,10 @@ public class SSIDReader: NSObject, ObservableObject, CLLocationManagerDelegate { private func notifyCurrentSSID() { Task { let currentSSID = await Utils.currentWifiSSID() ?? "" - publisher.send(currentSSID) - cancellables.removeAll() + await MainActor.run { + publisher.send(currentSSID) + cancellables.removeAll() + } } } diff --git a/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/MockVPNManagerStrategy.swift b/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/MockVPNManagerStrategy.swift index e6ac0ea4..7914deab 100644 --- a/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/MockVPNManagerStrategy.swift +++ b/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/MockVPNManagerStrategy.swift @@ -45,6 +45,7 @@ public class MockVPNManagerStrategy: VPNManagerStrategy { public func reinstate(configuration: VPNConfiguration) { } + @MainActor public func connect(configuration: VPNConfiguration) { guard currentState?.vpnStatus != .connected else { return @@ -58,6 +59,7 @@ public class MockVPNManagerStrategy: VPNManagerStrategy { } } + @MainActor public func disconnect() { stopCountingData() guard currentState?.vpnStatus != .disconnected else { @@ -92,6 +94,7 @@ public class MockVPNManagerStrategy: VPNManagerStrategy { dataCountTimer = nil } + @MainActor public func removeConfigurations() { disconnect() } diff --git a/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/TunnelKitVPNManagerStrategy.swift b/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/TunnelKitVPNManagerStrategy.swift index 127a8619..9b32f949 100644 --- a/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/TunnelKitVPNManagerStrategy.swift +++ b/PassepartoutLibrary/Sources/PassepartoutVPN/Managers/TunnelKitVPNManagerStrategy.swift @@ -67,7 +67,8 @@ public class TunnelKitVPNManagerStrategy: VPNManagerStrategy { // MARK: Protocol specific private var currentBundleIdentifier: String? - + + @MainActor public init(appGroup: String, tunnelBundleIdentifier: @escaping (VPNProtocolType) -> String, dataCountInterval: TimeInterval = 3.0) { self.appGroup = appGroup self.tunnelBundleIdentifier = tunnelBundleIdentifier @@ -107,6 +108,7 @@ public class TunnelKitVPNManagerStrategy: VPNManagerStrategy { // use this to drop redundant NE notifications vpnState .removeDuplicates() + .receive(on: DispatchQueue.main) .sink { self.currentState?.isEnabled = $0.isEnabled self.currentState?.vpnStatus = $0.vpnStatus