简体   繁体   中英

Problem binding a subclass to parent class in SwiftUI View

I've been experimenting on trying to binding subclass to a SwiftUI view that takes it parent class as a parameter.

These are my classes:

class Animal {
    func sound() -> String {
        return ""
    }
}

class Cat : Animal {
    override func sound() -> String {
        return "Meow"
    }
    
    func purr() {
        print("purring")
    }
}

class Dog : Animal {
    override func sound() -> String {
        return "Woof"
    }
    
    func fetch() {
        print("fetching")
    }
}

Here are the views I have set up.

struct ContentView: View {
    @State var creature:Cat = Cat()
    
    var body: some View {
        AnimalView(creature: $creature)
    }
}

struct AnimalView: View {
    @Binding var creature:Animal
    
    var body: some View {
        Text(creature.sound())
            .padding()
    }
}

This results in the compile error:

Cannot convert value of type 'Binding<Cat>' to expected argument type 'Binding<Animal>'

What the proper way to do bind to a view the takes a parent class?

Searching around I think the structure I would want is to make the view itself generic.

struct ContentView: View {
    @State var creature:Cat = Cat()
    @State var creature2:Dog = Dog()
    
    var body: some View {
        VStack {
        AnimalView(creature: $creature)
        AnimalView(creature: $creature2)
        }
    }
}

struct AnimalView<T:Animal> : View {
    @Binding var creature:T
    @State var sound:String = "No Sound"

    var body: some View {
        Text(creature.name)
            .padding()
            .onAppear {
                self.sound = self.creature.sound()
            }
    }
}

This will allow me to bind to types that inherit from Animal and let me use one view rather that having to create a separate Cat and Dog view.

Also just in case for better form, here is a same thing with protocol and classes.

protocol Animal {
    var name:String {
        get
    }
    
    func sound() -> String
}

struct Cat : Animal {
    var name:String {
        get {
            return "Cat"
        }
    }
    
    func sound() -> String {
        return "Meow"
    }
    
    func purr() {
        print("purring")
    }
}

struct Dog : Animal {
    var name:String {
        get {
            return "Dog"
        }
    }
    
    func sound() -> String {
        return "Woof"
    }
    
    func fetch() {
        print("fetching")
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM