I want to use the new .isLuminanceReduced Environment value while still retaining backwards compatibility with watchOS 7.
How can I add an availability check and provide a fallback in the case of running on < watchOS 8?
I want to use the new .isLuminanceReduced Environment value while still retaining backwards compatibility with watchOS 7.
How can I add an availability check and provide a fallback in the case of running on < watchOS 8?
You may need to add @available
on the struct using the new Environment value, and choose it using if #available
.
Something like this:
struct MyView_watchOS7OrLower: View {
var body: some View {
Circle()
.fill(Color.blue)
}
}
@available(watchOSApplicationExtension 8.0, *)
struct MyView_watchOS8OrHigher: View {
@Environment(\.isLuminanceReduced) var isLuminanceReduced
var body: some View {
if isLuminanceReduced {
Circle()
.stroke(Color.gray, lineWidth: 10)
} else {
Circle()
.fill(Color.white)
}
}
}
@ViewBuilder
func MyView() -> some View {
if #available(watchOS 8.0, *) {
MyView_watchOS8OrHigher()
} else {
MyView_watchOS7OrLower()
}
}
The answer I found to this is not really satisfying, but it works fine with SwiftUI.
Every time the variable isLuminanceReduced changes, the ExtensionDelegate also changes the app state and calls applicationWillResignActive()
.
So to keep backwards compatible I introduced a singleton class that just holds a Bool isOn:
class LuminanceReducedCompat: ObservableObject {
@Published var isOn: Bool = false
public static let shared = LuminanceReducedCompat()
private var notifcationObservers = [Any]()
private init() {}
}
Now you can change the isOn variable in the applicationWillResignActive()
.
On your SwiftUI views you can add a that object now as an observed object.
@ObservedObject var luminanceReducedCompat = LuminanceReducedCompat.shared
I know that's not really nice, but the best I found until now. I don't want to maintain 2 views that show the same. I though about using a custom Environment Value that reflects the official watchOS 8 value, but I am not sure how to push this into the view stack correctly and update it.
I thought I found a workable solution but it's no good. It only works in the fallback case and it breaks the feature for watchOS8:
struct IsLuminanceReduced: EnvironmentKey {
static var defaultValue: Bool = false
}
@available(watchOS, obsoleted: 8.0)
extension EnvironmentValues {
var isLuminanceReduced: Bool {
get { self[IsLuminanceReduced.self] }
set { self[IsLuminanceReduced.self] = newValue }
}
}
If I could figure out how to tell Swift "with watchOS8, * IGNORE this…"
Maybe you can pick up this fumble and carry it across the line?