【问题标题】:Generic type of a struct - SwiftUI结构的通用类型 - SwiftUI
【发布时间】:2021-03-17 17:40:11
【问题描述】:

我正在尝试将结构作为泛型类型传递(见模型)。我尝试使用 AnyView 来表示我的结构,但编译器在构建时出错:

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

我在 SwiftUI 中使用什么类型来表示泛型中的结构?

型号:

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()
    }
}

视图模型:

import SwiftUI

class MainCommunication {
    private var backend = MainBackend<AnyView>()
    
    // MARK: - Access to Model
    var navDirs: [MainBackend<AnyView>.NavDir] {
        backend.navDirs
    }
}

查看:

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())
        }
    }
}

【问题讨论】:

    标签: generics struct swiftui


    【解决方案1】:

    您将希望它们成为AnyView——这是将类型擦除到同质数组中的唯一方法。但是,您不能转换为 AnyView - 您必须将它们包装在 AnyView() 中。

    这意味着您实际上根本不需要泛型:

    
    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())
            }
        }
    }
    

    另请参阅:How to have a dynamic List of Views using SwiftUI

    【讨论】:

    • jnpdx,在你的回答中,请把“erase”这个词改成“ease”——这就是我认为你的意思。
    • @KeithB no - “擦除”正是我的意思。您可以在此处阅读有关类型擦除的信息:en.wikipedia.org/wiki/Type_erasure
    • jnpdx,我很抱歉。我没有意识到这一点。
    猜你喜欢
    • 2015-01-08
    • 1970-01-01
    • 2017-12-08
    • 1970-01-01
    • 2013-08-15
    • 1970-01-01
    • 1970-01-01
    • 2018-12-03
    • 2021-12-15
    相关资源
    最近更新 更多