Reputation: 23
I'm trying to pass a struct as a generic type (seen in Model). I tried using AnyView to represent my structs, but the complier errors out on build with:
Could not cast value of type 'EagleNation_macOS.NewsView' (0x10d7ff898) to 'SwiftUI.AnyView' (0x7fff82e27670).
2021-03-17 12:35:45.932135-0500 EagleNation-macOS[24102:2436828] Could not cast value of type 'EagleNation_macOS.NewsView' (0x10d7ff898) to 'SwiftUI.AnyView' (0x7fff82e27670).
Could not cast value of type 'EagleNation_macOS.NewsView' (0x10d7ff898) to 'SwiftUI.AnyView' (0x7fff82e27670).
What type do I use to represent a struct in a generic in SwiftUI?
Model:
import Foundation
struct MainBackend<Destination> {
let navDirs = [
NavDir(title: "News", dest: NewsView() as! Destination),
NavDir(title: "Bulletin", dest: BulletinView() as! Destination),
NavDir(title: "Clubs", dest: ClubsView() as! Destination),
]
struct NavDir: Identifiable {
let title: String
let dest: Destination
var id = UUID()
}
}
ViewModel:
import SwiftUI
class MainCommunication {
private var backend = MainBackend<AnyView>()
// MARK: - Access to Model
var navDirs: [MainBackend<AnyView>.NavDir] {
backend.navDirs
}
}
View:
import SwiftUI
struct MainView: View {
var body: some View {
NavigationView {
NavBar { NavDir in
NavDir.dest
}
NewsView()
}
}
}
struct NavBar<Destination: View>: View {
let navDirs = MainCommunication().navDirs
let buildDestination: (MainBackend<AnyView>.NavDir) -> Destination
var body: some View {
VStack() {
List(navDirs) { NavDir in
NavigationLink(destination: buildDestination(NavDir)) {
Text(NavDir.title)
}
}
.listStyle(SidebarListStyle())
}
}
}
Upvotes: 2
Views: 682
Reputation: 52407
You're going to want them to be AnyView
-- that's the only way to erase the types into a homogenous array. But, you can't cast to AnyView
-- you have to wrap them in AnyView()
.
This means you don't actually need the generic at all:
struct MainBackend {
let navDirs = [
NavDir(title: "News", dest: AnyView(NewsView())),
NavDir(title: "Bulletin", dest: AnyView(BulletinView())),
NavDir(title: "Clubs", dest: AnyView(ClubsView())),
]
struct NavDir: Identifiable {
let title: String
let dest: AnyView
var id = UUID()
}
}
class MainCommunication {
private var backend = MainBackend()
// MARK: - Access to Model
var navDirs: [MainBackend.NavDir] {
backend.navDirs
}
}
struct MainView: View {
var body: some View {
NavigationView {
NavBar { NavDir in
NavDir.dest
}
}
}
}
struct NavBar<Destination: View>: View {
let navDirs = MainCommunication().navDirs
let buildDestination: (MainBackend.NavDir) -> Destination
var body: some View {
VStack() {
List(navDirs) { NavDir in
NavigationLink(destination: buildDestination(NavDir)) {
Text(NavDir.title)
}
}
.listStyle(SidebarListStyle())
}
}
}
See also: How to have a dynamic List of Views using SwiftUI
Upvotes: 1