From 3cf702d9427c1bc7b35bbe6a5c361327efa25271 Mon Sep 17 00:00:00 2001 From: Ryan Lepinski Date: Sat, 27 May 2023 08:54:24 -0700 Subject: [PATCH] Fix watchOS --- Airship/AirshipCore/Source/Airship.swift | 6 +- .../Source/AppStateTrackerAdapter.swift | 15 ++-- .../AirshipCore/Source/DeepLinkAction.swift | 1 + .../DefaultAppIntegrationDelegate.swift | 73 ++++++++----------- .../Source/OpenExternalURLAction.swift | 1 + Airship/AirshipCore/Source/Pager.swift | 2 +- .../Source/WorkBackgroundTasks.swift | 14 ++-- 7 files changed, 56 insertions(+), 56 deletions(-) diff --git a/Airship/AirshipCore/Source/Airship.swift b/Airship/AirshipCore/Source/Airship.swift index f907b9046..7a56bb532 100644 --- a/Airship/AirshipCore/Source/Airship.swift +++ b/Airship/AirshipCore/Source/Airship.swift @@ -271,6 +271,7 @@ public class Airship: NSObject { /// Initalizes Airship. Config will be read from `AirshipConfig.plist`. @objc + @MainActor public class func takeOff() { takeOff(nil) } @@ -279,7 +280,8 @@ public class Airship: NSObject { /// - Parameters: /// - config: The Airship config. @objc - public class func takeOff(_ config: Config?) { + @MainActor + public class func takeOff(_ config: AirshipConfig?) { guard Thread.isMainThread else { fatalError("TakeOff must be called on the main thread.") @@ -304,7 +306,7 @@ public class Airship: NSObject { } } - let resolvedConfig = config?.copy() as? Config ?? Config.default() + let resolvedConfig = config?.copy() as? AirshipConfig ?? AirshipConfig.default() guard resolvedConfig.validate() else { AirshipLogger.impError("Config is invalid. Unable to takeOff.") diff --git a/Airship/AirshipCore/Source/AppStateTrackerAdapter.swift b/Airship/AirshipCore/Source/AppStateTrackerAdapter.swift index c7f2eeeca..a65e4cc40 100644 --- a/Airship/AirshipCore/Source/AppStateTrackerAdapter.swift +++ b/Airship/AirshipCore/Source/AppStateTrackerAdapter.swift @@ -22,7 +22,7 @@ enum AppLifeCycleEvent: Sendable { #if os(watchOS) -final class DefaultAppStateTrackerAdapter: ApplicationStateProvider, Sendable { +final class DefaultAppStateTrackerAdapter: AppStateTrackerAdapter, Sendable { var state: ApplicationState { let appState = WKExtension.shared().applicationState switch appState { @@ -49,7 +49,7 @@ final class DefaultAppStateTrackerAdapter: ApplicationStateProvider, Sendable { object: nil, queue: nil, using: { _ in - MainActor.runUnsafe { + DefaultAppStateTrackerAdapter.runUnsafe { eventHandler(.didBecomeActive) } } @@ -61,7 +61,7 @@ final class DefaultAppStateTrackerAdapter: ApplicationStateProvider, Sendable { object: nil, queue: nil, using: { _ in - MainActor.runUnsafe { + DefaultAppStateTrackerAdapter.runUnsafe { eventHandler(.willResignActive) } } @@ -73,7 +73,7 @@ final class DefaultAppStateTrackerAdapter: ApplicationStateProvider, Sendable { object: nil, queue: nil, using: { _ in - MainActor.runUnsafe { + DefaultAppStateTrackerAdapter.runUnsafe { eventHandler(.willEnterForeground) } } @@ -85,12 +85,17 @@ final class DefaultAppStateTrackerAdapter: ApplicationStateProvider, Sendable { object: nil, queue: nil, using: { _ in - MainActor.runUnsafe { + DefaultAppStateTrackerAdapter.runUnsafe { eventHandler(.didEnterBackground) } } ) } + + @MainActor(unsafe) + static func runUnsafe(_ block: @MainActor () -> Void) { + block() + } } #else final class DefaultAppStateTrackerAdapter: AppStateTrackerAdapter, Sendable { diff --git a/Airship/AirshipCore/Source/DeepLinkAction.swift b/Airship/AirshipCore/Source/DeepLinkAction.swift index 147bb8144..18e6d4e66 100644 --- a/Airship/AirshipCore/Source/DeepLinkAction.swift +++ b/Airship/AirshipCore/Source/DeepLinkAction.swift @@ -73,6 +73,7 @@ public class DeepLinkAction: NSObject, Action { #else WKExtension.shared().openSystemURL(url) + return ActionResult.empty() #endif } diff --git a/Airship/AirshipCore/Source/DefaultAppIntegrationDelegate.swift b/Airship/AirshipCore/Source/DefaultAppIntegrationDelegate.swift index 89077a03d..e33368e43 100644 --- a/Airship/AirshipCore/Source/DefaultAppIntegrationDelegate.swift +++ b/Airship/AirshipCore/Source/DefaultAppIntegrationDelegate.swift @@ -265,62 +265,51 @@ class DefaultAppIntegrationDelegate: NSObject, AppIntegrationDelegate { presentationOptions: UNNotificationPresentationOptions?, completionHandler: @escaping (WKBackgroundFetchResult) -> Void ) { - AirshipLogger.info( - "Application received remote notification: \(userInfo)" - ) + Task { + AirshipLogger.info( + "Application received remote notification: \(userInfo)" + ) - let situation = + let situation = isForeground ? Situation.foregroundPush : Situation.backgroundPush - let dispatchGroup = DispatchGroup() - var fetchResults: [UInt] = [] - let lock = AirshipLock() - var metadata: [AnyHashable: Any] = [:] - metadata[UAActionMetadataPushPayloadKey] = userInfo + let dispatchGroup = DispatchGroup() + var fetchResults: [UInt] = [] + let lock = AirshipLock() + var metadata: [AnyHashable: Any] = [:] + metadata[UAActionMetadataPushPayloadKey] = userInfo - if let presentationOptions = presentationOptions { - metadata[UAActionMetadataForegroundPresentationKey] = + if let presentationOptions = presentationOptions { + metadata[UAActionMetadataForegroundPresentationKey] = self.isForegroundPresentation(presentationOptions) - } + } - // Pushable components - self.pushableComponents.forEach { - if $0.receivedRemoteNotification != nil { - dispatchGroup.enter() - $0.receivedRemoteNotification?(userInfo) { fetchResult in - lock.sync { - fetchResults.append(fetchResult.rawValue) + // Pushable components + self.pushableComponents.forEach { + if $0.receivedRemoteNotification != nil { + dispatchGroup.enter() + $0.receivedRemoteNotification?(userInfo) { fetchResult in + lock.sync { + fetchResults.append(fetchResult.rawValue) + } + dispatchGroup.leave() } - dispatchGroup.leave() } } - } - // Actions -> Push - dispatchGroup.enter() - ActionRunner.run( - actionValues: userInfo, - situation: situation, - metadata: metadata - ) { result in + + let result = await ActionRunner.run( + actionValues: userInfo, + situation: situation, + metadata: metadata + ) lock.sync { fetchResults.append(UInt(result.fetchResult.rawValue)) } - self.push.didReceiveRemoteNotification( - userInfo, - isForeground: isForeground - ) { pushResult in - lock.sync { - let result: WKBackgroundFetchResult = - pushResult as! WKBackgroundFetchResult - fetchResults.append(result.rawValue) - } - dispatchGroup.leave() - } - } - dispatchGroup.notify(queue: .main) { - completionHandler(Utils.mergeFetchResults(fetchResults)) + dispatchGroup.notify(queue: .main) { + completionHandler(AirshipUtils.mergeFetchResults(fetchResults)) + } } } #endif diff --git a/Airship/AirshipCore/Source/OpenExternalURLAction.swift b/Airship/AirshipCore/Source/OpenExternalURLAction.swift index ef701231a..6dd4ed872 100644 --- a/Airship/AirshipCore/Source/OpenExternalURLAction.swift +++ b/Airship/AirshipCore/Source/OpenExternalURLAction.swift @@ -64,6 +64,7 @@ public class OpenExternalURLAction: NSObject, Action { #else WKExtension.shared().openSystemURL(url) + return ActionResult(value: url.absoluteString) #endif } diff --git a/Airship/AirshipCore/Source/Pager.swift b/Airship/AirshipCore/Source/Pager.swift index a5d3e7be1..c0dd4bfaf 100644 --- a/Airship/AirshipCore/Source/Pager.swift +++ b/Airship/AirshipCore/Source/Pager.swift @@ -602,7 +602,7 @@ fileprivate extension View { action: @escaping ([PagerGestureLocation]) -> Void ) -> some View { #if !os(tvOS) - if #available(iOS 16.0, *) { + if #available(iOS 16.0, watchOS 9.0, *) { let pagerGestureEplorer = PagerGestureMapExplorer( CGRect( x: 0, diff --git a/Airship/AirshipCore/Source/WorkBackgroundTasks.swift b/Airship/AirshipCore/Source/WorkBackgroundTasks.swift index 793ce5c2a..105aa0175 100644 --- a/Airship/AirshipCore/Source/WorkBackgroundTasks.swift +++ b/Airship/AirshipCore/Source/WorkBackgroundTasks.swift @@ -13,14 +13,22 @@ protocol WorkBackgroundTasksProtocol: Sendable { final class WorkBackgroundTasks: WorkBackgroundTasksProtocol, Sendable { + #if !os(watchOS) private let requestMap: AirshipMainActorWrapper<[UInt: UIBackgroundTaskIdentifier]> = AirshipMainActorWrapper([:]) private let nextRequestID: AirshipMainActorWrapper = AirshipMainActorWrapper(0) + #endif @MainActor func beginTask( _ name: String, expirationHandler: (@Sendable () -> Void)? = nil ) throws -> AirshipCancellable { + #if os(watchOS) + let cancellable: CancellabelValueHolder = CancellabelValueHolder(value: 0) { _ in + } + return cancellable + #else + AirshipLogger.trace("Requesting task: \(name)") let requestID = nextRequestID.value @@ -32,11 +40,6 @@ final class WorkBackgroundTasks: WorkBackgroundTasksProtocol, Sendable { } } - #if os(watchOS) - return cancellable - #else - - let application = UIApplication.shared self.requestMap.value[requestID] = application.beginBackgroundTask(withName: name) { AirshipLogger.trace("Task expired: \(name)") @@ -56,7 +59,6 @@ final class WorkBackgroundTasks: WorkBackgroundTasksProtocol, Sendable { @MainActor private func cancel(requestID: UInt) { #if !os(watchOS) - guard let taskID = self.requestMap.value.removeValue(forKey: requestID), taskID != UIBackgroundTaskIdentifier.invalid else {