Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Type 'any ProtocolName' cannot conform to '(ProtocolName's Inherited Protocol)'

I have a ProtocolName that conforms to ObservableObject. I then have ClassName that conforms to ProtocolName.

However, when I try to use @ObservedObject serviceName: ProtocolName = ClassName, it fails to build with the following message: "Type ‘any ProtocolName’ cannot conform to ‘ObservableObject’"

What am I doing wrong and how can I fix this?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Example:

protocol ProtocolName: ObservableObject {
    let random: String
}

class ClassName: ProtocolName {
    let random: String
}

@ObservedObject serviceName: ProtocolName = ClassName()

>Solution :

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 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.")
    }
}

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())
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading