When you write a line like this:
@ObservedObject var observeMe: ProtocolName
You are saying that observeMe
is a box that can contain any kind of thing that conforms to the ProtocolName
protocol"
The type of that box is any ProtocolName
it's called an existential
.
But the box itself does NOT conform to ProtocolName
(and by extension does not conform to ObservableObject
). The thing inside the box does, but the box itself does not.
So the compiler complains that the existential whose type is any ProtocolName
is not an ObservableObject
You can make the box even more obvious and explicit using the any ProtocolName
syntax:
import SwiftUI
import Combine
protocol ProtocolName: ObservableObject {
var someValue: Int { get }
}
class MyClass: ProtocolName {
@Published var someValue: Int = 42
}
struct SomeStruct : View {
@ObservedObject var observeMe: any ProtocolName = MyClass()
var body: some View {
Text("Hello.")
}
}
And you'll still see the error.
To solve the problem your @ObservedObject
has to be a concrete type that conforms to ProtocolName
:
import SwiftUI
import Combine
protocol ProtocolName: ObservableObject {
var someValue: Int { get }
}
class MyClass: ProtocolName {
@Published var someValue: Int = 42
}
struct SomeStruct : View {
@ObservedObject var observeMe: MyClass = MyClass()
var body: some View {
Text("Hello.")
}
}
let myView = SomeStruct()
Or you can add a type parameter to your view so that when the view is created there is a specific type that conforms to the protocol that is used for the view:
import SwiftUI
import Combine
protocol ProtocolName: ObservableObject {
var someValue: Int { get set }
}
class MyClass: ProtocolName {
@Published var someValue: Int = 42
}
struct SomeStruct<T : ProtocolName> : View {
@ObservedObject var observeMe:T
var body: some View {
Text("Hello.")
Button(action: {observeMe.someValue = 3}) {
Text("Button")
}
}
}
let myView = SomeStruct(observeMe: MyClass())