From 265beb5bc9071a392e96a5b206b49ffc1403118e Mon Sep 17 00:00:00 2001 From: NachoSoto Date: Thu, 8 Sep 2022 10:53:06 -0700 Subject: [PATCH] `watchOS`: fixed crash when ran on single-target apps with Xcode 14 and before watchOS 9.0 Follow up to #1849. That fix was incomplete, and still crashed when ran before watchOS 9.0. Fixes [SDKONCALL-119] and [CSDK-416] and #1891. There are 3 variables we need to take into account: - `watchOS` version - Xcode version - Dual/single target app | watchOS | Xcode | Dual / Single target | Before PR | With this PR | |---------------|-----------|----------------------|--------------------|-------------------| | < 9.0 | < 14.x | Single | `WKExtension` | `WKExtension` | | < 9.0 | < 14.x | Dual | N/A | N/A | | < 9.0 | >= 14.0 | Single | crash :warning: | always `false` | | < 9.0 | >= 14.0 | Dual | `WKApplication` | `WKExtension` | | >= 9.0 | >= 14.0 | Single | `WKApplication` | `WKApplication` | | >= 9.0 | >= 14.0 | Dual | `WKApplication` | `WKApplication` | --- Sources/Misc/SystemInfo.swift | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/Sources/Misc/SystemInfo.swift b/Sources/Misc/SystemInfo.swift index b782d4c3a3..31bfdeb860 100644 --- a/Sources/Misc/SystemInfo.swift +++ b/Sources/Misc/SystemInfo.swift @@ -52,7 +52,7 @@ class SystemInfo { } static var systemVersion: String { - return ProcessInfo().operatingSystemVersionString + return ProcessInfo.processInfo.operatingSystemVersionString } static var appVersion: String { @@ -227,22 +227,36 @@ private extension SystemInfo { #elseif os(watchOS) var isApplicationBackgroundedWatchOS: Bool { - // In Xcode 13 and earlier the system divides a watchOS app into two sections: - // - WatchKit app - // - WatchKit extension + var isSingleTargetApplication: Bool { + return Bundle.main.infoDictionary?.keys.contains("WKApplication") == true + } + // In Xcode 14 and later, you can produce watchOS apps with a single watchOS app target. // These single-target watchOS apps can run on watchOS 7 and later. - // Calling `WKExtension.shared` on these single-target apps crashes. - // - // `WKApplication` provides a more accurate value if it's available, and it avoids that crash. #if swift(>=5.7) - if #available(watchOS 7.0, *) { + if #available(watchOS 7.0, *), self.isOperatingSystemAtLeast(.init(majorVersion: 9, + minorVersion: 0, + patchVersion: 0)) { + // `WKApplication` works on both dual-target and single-target apps + // When running on watchOS 9.0+ return WKApplication.shared().applicationState == .background } else { - return WKExtension.shared().applicationState == .background + if isSingleTargetApplication { + // Before watchOS 9.0, single-target apps don't allow using `WKExtension` or `WKApplication` + // (see https://github.com/RevenueCat/purchases-ios/issues/1891) + // So we can't detect if it's running in the background + return false + } else { + return WKExtension.shared().applicationState == .background + } } #else - // Before Xcode 14, single-target extensions aren't supported (and WKApplication isn't available) + // In Xcode 13 and earlier the system divides a watchOS app into two sections + // (single-target apps are not supported): + // - WatchKit app + // - WatchKit extension + + // Before Xcode 14, single-target extensions aren't supported (and `WKApplication` isn't available) return WKExtension.shared().applicationState == .background #endif }