Hi. I'm trying to figure out the way to access projected values of custom wrappers holding optional values and face Type of expression is ambiguous without more context
errors in Swift 5.2.4 (Xcode 11.5). Here is the code that I have that works fine with non optional types, and solutions that I tried.
I have a custom wrapper TestWrapper
(it could be a property wrapper by itself but I can't figure out proper way to implement DynamicProperty so have to use it as it is) used with @ObservedObject. Then the object that I wrap and observe itself contains a property with another property wrapper. Now I used dynamic member lookup on TestWrapper
to access property of wrapped value via key path.
@dynamicMemberLookup
public class TestWrapper<T>: ObservableObject {
@Published var wrappedValue: T
public init(_ wrappedValue: T) {
self.wrappedValue = wrappedValue
}
public subscript<U>(dynamicMember keyPath: KeyPath<T, U>) -> U {
wrappedValue[keyPath: keyPath]
}
}
@propertyWrapper
struct TestPropertyWrapper {
var wrappedValue: String
var projectedValue: Int { wrappedValue.count }
}
struct TestObject {
@TestPropertyWrapper
var string: String
}
Then I can use it with no problems like this:
struct RootView: View {
@ObservedObject var testValue: TestWrapper<TestObject>
= TestWrapper(TestObject(string: "hello"))
var body: some View {
let lenght = testValue.$string
return EmptyView()
}
}
But as soon as I change from TestObject
to TestObject?
I got ambiguous type error (also happens on regular key paths, so projected value key path is not the issue):
struct RootView: View {
@ObservedObject var testValue: TestWrapper<TestObject?>
= TestWrapper(TestObject(string: "hello"))
var body: some View {
let lenght = testValue.$string // Type of expression is ambiguous without more context
return EmptyView()
}
}
Now what I have already tried and what didn't solve the issue:
- define a second dynamic member lookup (or change original implementation) subscript on
T?
, same error - define a protocol to constrain
TestWrapper.T
thatOptional
would also implement, same error:
protocol TestProtocol {}
extension Optional: TestProtocol where Wrapped: TestProtocol {}
public class TestWrapper<T: TestProtocol>: ObservableObject { ... }
struct TestObject: TestProtocol { ... }
- remove property wrapper from
var string: String
and access it liketestValue.string
, same result (so property wrapper is not to blame)
Any suggestions how this can be solved?