commit f54e0f8551db654c7ed4b064840755209ce5fece parent d948bb6a33a2b0e9a9015b96054642e5fade0c1b Author: Marc Stibane <marc@taler.net> Date: Mon, 18 Sep 2023 08:38:41 +0200 MainActor for Swift 6 Diffstat:
17 files changed, 32 insertions(+), 26 deletions(-)
diff --git a/TalerWallet1/Backend/WalletCore.swift b/TalerWallet1/Backend/WalletCore.swift @@ -151,7 +151,7 @@ extension WalletCore { private func postNotification(_ aName: NSNotification.Name, object anObject: Any? = nil, userInfo: [AnyHashable: Any]? = nil) { - Task { + Task { // runs on MainActor if let userInfo { symLog.log(userInfo) } else { symLog.log(aName) } await postNotificationM(aName, object: anObject, userInfo: userInfo) logger.log("Notification sent: \(aName.rawValue)") @@ -182,7 +182,7 @@ extension WalletCore { logger.log("❗️ \(pendingOp, privacy: .public): \(id, privacy: .public)") // this is a new pendingOp I haven't seen before } } - private func handleStateTransition(_ jsonData: Data) throws { + @MainActor private func handleStateTransition(_ jsonData: Data) throws { do { let decoded = try JSONDecoder().decode(TransactionTransition.self, from: jsonData) if decoded.newTxState != decoded.oldTxState { @@ -206,7 +206,7 @@ extension WalletCore { } } - private func handleNotification(_ anyCodable: AnyCodable?) throws { + @MainActor private func handleNotification(_ anyCodable: AnyCodable?) throws { guard let anyPayload = anyCodable else { throw WalletBackendError.deserializationError } do { let jsonData = try JSONEncoder().encode(anyPayload) @@ -256,7 +256,7 @@ print("\n❗️ WalletCore.swift:226 Notification: ", anyPayload, "\n") / } /// here not only responses, but also notifications from wallet-core will be received - func handleMessage(message: String) { + @MainActor func handleMessage(message: String) { do { var asyncDelay = 0 if let delay: Bool = developDelay { // Settings: 2 seconds delay diff --git a/TalerWallet1/Helper/Controller+playSound.swift b/TalerWallet1/Helper/Controller+playSound.swift @@ -9,7 +9,7 @@ import UIKit extension Controller { /// 0 = failure, 1 = received, 2 = sent - func playSound(_ number: Int) { + @MainActor func playSound(_ number: Int) { var soundID: SystemSoundID = 0 let notificationGenerator = useHaptics ? UINotificationFeedbackGenerator() : nil if number > 9 { diff --git a/TalerWallet1/Helper/Font+Taler.swift b/TalerWallet1/Helper/Font+Taler.swift @@ -165,6 +165,7 @@ struct NavigationBarBuilder: UIViewControllerRepresentable { } /// This works only once. Each following call does nothing - including (re-)setting to nil +@MainActor struct TalerNavBar: ViewModifier { let talerFont: Int @@ -191,7 +192,7 @@ struct TalerNavBar: ViewModifier { } extension View { - func talerNavBar(talerFont: Int) -> some View { + @MainActor func talerNavBar(talerFont: Int) -> some View { self.modifier(TalerNavBar(talerFont)) } } diff --git a/TalerWallet1/Helper/KeyboardResponder.swift b/TalerWallet1/Helper/KeyboardResponder.swift @@ -19,6 +19,7 @@ import Combine import UIKit +@MainActor public final class KeyboardResponder: ObservableObject { @Published public var keyboardHeight: CGFloat = 0 diff --git a/TalerWallet1/Helper/View+Notification.swift b/TalerWallet1/Helper/View+Notification.swift @@ -64,7 +64,7 @@ extension View { } } - func onAppEnteredBackground( + @MainActor func onAppEnteredBackground( perform action: @escaping () -> Void ) -> some View { onNotification( diff --git a/TalerWallet1/Helper/View+dismissTop.swift b/TalerWallet1/Helper/View+dismissTop.swift @@ -22,7 +22,7 @@ import SwiftUI /// A presented sheet (SwiftUI view) doesn't always close when calling "dismiss()" provided by @Environment(\.dismiss), /// so we are walking the view stack to find the top presentedViewController (UIKit) and dismiss it. extension View { - public func dismissTop(animated: Bool = true) { + @MainActor public func dismissTop(animated: Bool = true) { let windows = UIApplication.shared.connectedScenes.compactMap { ($0 as? UIWindowScene)?.keyWindow // TODO: iPad might have more than 1 window } diff --git a/TalerWallet1/Views/Balances/BalancesListView.swift b/TalerWallet1/Views/Balances/BalancesListView.swift @@ -69,6 +69,7 @@ struct BalancesListView: View { }) } + /// runs on MainActor if called in some Task {} private func reloadAction() async -> Int { let reloaded = await model.balancesM() let count = reloaded.count @@ -160,7 +161,7 @@ extension BalancesListView { if shouldReload { shouldReload = false symLog?.log(".onAppear ==> shouldReload was true, reloading now") - Task { await reloadAction() } + Task { await reloadAction() } // runs on MainActor } } .onDisappear() { diff --git a/TalerWallet1/Views/Exchange/ExchangeListView.swift b/TalerWallet1/Views/Exchange/ExchangeListView.swift @@ -24,7 +24,7 @@ struct ExchangeListView: View { } func addExchange(_ exUrl: String) -> Void { - Task { + Task { // runs on MainActor symLog.log("adding: \(exUrl)") do { try await model.addExchange(url: exUrl) @@ -124,7 +124,7 @@ extension ExchangeListView { .onNotification(.ExchangeAdded) { notification in // doesn't need to be received on main thread because we just reload in the background anyway symLog?.log(".onNotification(.ExchangeAdded) ==> reloading exchanges") - Task { await reloadAction() } + Task { await reloadAction() } // runs on MainActor } } // body } diff --git a/TalerWallet1/Views/HelperViews/CopyShare.swift b/TalerWallet1/Views/HelperViews/CopyShare.swift @@ -37,6 +37,7 @@ struct CopyButton: View { } } // MARK: - +@MainActor struct ShareButton: View { private let symLog = SymLogV(0) @Environment(\.isEnabled) private var isEnabled: Bool diff --git a/TalerWallet1/Views/HelperViews/CurrencyField.swift b/TalerWallet1/Views/HelperViews/CurrencyField.swift @@ -22,6 +22,7 @@ import SwiftUI import UIKit +@MainActor public struct CurrencyField: View { @Binding var value: UInt64 var currency: String @@ -88,6 +89,7 @@ class NoCaretTextField: UITextField { } } +@MainActor struct CurrencyInputField: UIViewRepresentable { @Binding var value: UInt64 var formatter: NumberFormatter @@ -97,11 +99,11 @@ struct CurrencyInputField: UIViewRepresentable { Coordinator(self) } - public func becomeFirstResponder() -> Void { + @MainActor public func becomeFirstResponder() -> Void { textField.becomeFirstResponder() } - public func resignFirstResponder() -> Void { + @MainActor public func resignFirstResponder() -> Void { textField.resignFirstResponder() } diff --git a/TalerWallet1/Views/HelperViews/TransactionButton.swift b/TalerWallet1/Views/HelperViews/TransactionButton.swift @@ -19,7 +19,7 @@ struct TransactionButton: View { : isDestructive ? .destructive : nil Button(role: role, action: { - Task { + Task { // runs on MainActor disabled = true // don't try this more than once do { try await action(transactionId) diff --git a/TalerWallet1/Views/Payment/PayTemplateView.swift b/TalerWallet1/Views/Payment/PayTemplateView.swift @@ -21,7 +21,7 @@ struct PayTemplateView: View { @EnvironmentObject private var model: WalletModel func acceptAction(preparePayResult: PreparePayResult) { - Task { + Task { // runs on MainActor do { let confirmPayResult = try await model.confirmPayM(preparePayResult.transactionId) // symLog.log(confirmPayResult as Any) diff --git a/TalerWallet1/Views/Payment/PaymentView.swift b/TalerWallet1/Views/Payment/PaymentView.swift @@ -21,7 +21,7 @@ struct PaymentView: View { @EnvironmentObject private var model: WalletModel func acceptAction(preparePayResult: PreparePayResult) { - Task { + Task { // runs on MainActor do { let confirmPayResult = try await model.confirmPayM(preparePayResult.transactionId) // symLog.log(confirmPayResult as Any) diff --git a/TalerWallet1/Views/Settings/SettingsView.swift b/TalerWallet1/Views/Settings/SettingsView.swift @@ -57,7 +57,7 @@ struct SettingsView: View { Button("Reset", role: .destructive) { didReset = true showResetAlert = false - Task { + Task { // runs on MainActor symLog.log("❗️Reset wallet-core❗️") do { try await model.resetWalletCoreT() @@ -112,7 +112,7 @@ struct SettingsView: View { description: String(localized: "Get money for testing")) { Button("Withdraw") { withDrawDisabled = true // don't run twice - Task { + Task { // runs on MainActor symLog.log("Withdraw KUDOS") do { try await model.loadTestKudosM(test: false) @@ -128,7 +128,7 @@ struct SettingsView: View { description: String(localized: "Get money for testing")) { Button("Withdraw") { withDrawDisabled = true // don't run twice - Task { + Task { // runs on MainActor symLog.log("Withdraw TESTKUDOS") do { try await model.loadTestKudosM(test: true) @@ -144,7 +144,7 @@ struct SettingsView: View { description: String(localized: "Perform basic test transactions")) { Button("Demo 1") { checkDisabled = true // don't run twice - Task { + Task { // runs on MainActor symLog.log("running integration test on demo") do { try await model.runIntegrationTestM(newVersion: false, test: false) @@ -160,7 +160,7 @@ struct SettingsView: View { description: String(localized: "Perform basic test transactions")) { Button("Test 1") { checkDisabled = true // don't run twice - Task { + Task { // runs on MainActor symLog.log("running integration test on test") do { try await model.runIntegrationTestM(newVersion: false, test: true) @@ -176,7 +176,7 @@ struct SettingsView: View { description: String(localized: "Perform more test transactions")) { Button("Demo 2") { checkDisabled = true // don't run twice - Task { + Task { // runs on MainActor symLog.log("running integration test V2 on demo") do { try await model.runIntegrationTestM(newVersion: true, test: false) @@ -192,7 +192,7 @@ struct SettingsView: View { description: String(localized: "Perform more test transactions")) { Button("Test 2") { checkDisabled = true // don't run twice - Task { + Task { // runs on MainActor symLog.log("running integration test V2 on test") do { try await model.runIntegrationTestM(newVersion: true, test: true) diff --git a/TalerWallet1/Views/Sheets/ShareSheet.swift b/TalerWallet1/Views/Sheets/ShareSheet.swift @@ -21,7 +21,7 @@ import SymLog public class ShareSheet: ObservableObject { private let symLog = SymLogC() - static func shareSheet(url: String) { + @MainActor static func shareSheet(url: String) { let url = URL(string: url) let activityView = UIActivityViewController(activityItems: [url!], applicationActivities: nil) diff --git a/TalerWallet1/Views/Transactions/TransactionDetailView.swift b/TalerWallet1/Views/Transactions/TransactionDetailView.swift @@ -127,7 +127,7 @@ struct TransactionDetailView: View { } else { symLog.log("ignoring newTxState.major: \(newMajor)") } - } else { Task { + } else { Task { // runs on MainActor do { symLog.log("newState: \(newMajor), reloading transaction") withAnimation() { transaction = Transaction(dummyCurrency: DEMOCURRENCY); viewId = UUID() } diff --git a/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawTOSView.swift b/TalerWallet1/Views/WithdrawBankIntegrated/WithdrawTOSView.swift @@ -24,7 +24,7 @@ struct WithdrawTOSView: View { var body: some View { VStack { Content(symLog: symLog, exchangeTOS: exchangeTOS, myListStyle: $myListStyle) { - Task { + Task { // runs on MainActor do { if let exchangeBaseUrl { _ = try await model.setExchangeTOSAcceptedM(exchangeBaseUrl, etag: exchangeTOS!.currentEtag)