Skip to content

Instantly share code, notes, and snippets.

@PaulWoodIII
Created August 4, 2019 13:26
Show Gist options
  • Select an option

  • Save PaulWoodIII/914018cfdbb0ed23dfa5fccd508b740c to your computer and use it in GitHub Desktop.

Select an option

Save PaulWoodIII/914018cfdbb0ed23dfa5fccd508b740c to your computer and use it in GitHub Desktop.
How to solve rendering a Heterogeneous collection when you are required to use a Homogeneous List of Objects in SwiftUI, In short use a Wrapper / Box around the content
//
// ListOfAnimals.swift
// AnimalList
//
// Created by Paul Wood on 8/4/19.
// Copyright © 2019 Paul Wood. All rights reserved.
//
import SwiftUI
protocol Animal {
var displayName: String { get }
var action: () -> () { get } // a closure that does some work
}
struct Dog: Animal {
private var name: String
var displayName: String {
return "I'm a Good Dog named: \(name)"
}
var action: () -> () {
get {
return self.bark
}
}
init(_ value: String) {
self.name = value
}
func bark() {
print("bark")
}
}
struct Cat: Animal {
var name: String
var displayName: String {
return "I'm the best Cat named: \(name)"
}
var action: () -> () {
get {
return self.meow
}
}
init(_ value: String) {
self.name = value
}
func meow() {
print("meow")
}
}
struct Bat {
var name: String = "Dracula"
func scaryNoises() {
print("Muahahahahah am I really an Animal? No I'm Dracula")
}
}
//: Wrapper around the specialized name types above
//: We know how this type will be used so now it conforms to Identifiable
//: instead of the models above
struct AnimalHolder: Animal, Identifiable {
var id: UUID
var displayName: String
var action: () -> ()
init<U>(nameable name: U) where U: Animal {
self.displayName = name.displayName
self.action = name.action
self.id = UUID()
}
init(bat: Bat) {
self.displayName = "I'm a bat"
self.action = bat.scaryNoises
self.id = UUID()
}
}
let animals: [AnimalHolder] = [
AnimalHolder(nameable: Dog("Alice")),
AnimalHolder(nameable: Dog("Bob")),
AnimalHolder(nameable: Cat("Clark")),
AnimalHolder(nameable: Cat("Davis")),
AnimalHolder(nameable: Dog("Elanore")),
AnimalHolder(nameable: Dog("Frank")),
AnimalHolder(nameable: Cat("Gonzalez")),
AnimalHolder(nameable: Cat("Harris")),
AnimalHolder(nameable: Cat("Harris")), //Can Duplicate
AnimalHolder(nameable: Dog("Harris")), // Can go across types
AnimalHolder(bat: Bat())
]
struct AnimalDetail: View {
var animal: AnimalHolder
var body: some View {
VStack {
Spacer()
Text("Animal").font(.title)
Text(animal.displayName).font(.body)
Button(action: {
print("play pressed")
self.animal.action()
}, label: {
Image(systemName: "play")
Text("Make My Noise")
})
.foregroundColor(Color.white)
.padding()
.background(Color.blue)
.cornerRadius(5)
Spacer()
}
}
}
struct ListOfAnimals: View {
var body: some View {
NavigationView {
List(animals) { animal in
NavigationLink(destination: AnimalDetail(animal: animal)) {
HStack {
Text(animal.displayName)
}
}
}
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
MultipleIdentifiableList()
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment