首页 > 解决方案 > 如何解决 Swift 泛型类型转换

问题描述

我有这样的代码

import SwiftUI

struct TabItemModifier<TabItem>: ViewModifier where TabItem: View {

    var tabItem: () -> TabItem

    func body(content: Content) -> some View {
        return TabItemView(tabItem: tabItem, content: content)
    }
}

struct TabItemView<TabItem, Content> : View where Content: View, TabItem : View {

    var tabItem: () -> TabItem
    var content: Content

    var body: some View {
        content
    }
}


extension View {

    func withTabItem<V>(@ViewBuilder _ label: @escaping () -> V) -> some View where V: View{
        ModifiedContent(content: self, modifier: TabItemModifier(tabItem: label))
    }
}

它应用修饰符 withTabItem,它应该返回某种类型的 TabItemView,其中包含属性中的 tabItem 和内容,并且只呈现内容。

然后在代码中的其他地方,我想将 View 转换为这个 TabItemView 以从它访问 tabItem 属性,如下所示:

if let tabbed = views.0 as? TabItemView {
      tabItems.append(tabbed.tabItem())
 }

但是这种铸造是不可能的。

更新

我已经这样改了

 var body: some View {

        MenuView {

            Page1()

            Page2()
                .menuTabItem(tag: 1) {
                   TabItemView(systemImage: "person", title: "Tab 2")
                }

而这个ViewModifier的新实现很简单,像这样

 func menuTabItem<T>(tag: Int, @ViewBuilder _ tabItem: @escaping () -> T) -> some View
                       where T: View {

        ModifiedContent(content: AnyView(self),
                           modifier: Click5MenuItemModifier(
                                tag: tag,
                                menuItem: nil,
                                tabItem:  AnyView(tabItem())
            )
        )
    } 


struct MenuItemModifier: ViewModifier {

    var tag: Int
    var menuItem: AnyView?
    var tabItem: AnyView?

    func body(content: Content) -> some View {
        return content
    }
}

但问题是我只能在 MenuView 中直接使用它。在 Page1() 中使用此修饰符,导致该视图隐藏在 Page1 下,然后在 MenuView 的实现中我无法通过上述转换访问此修饰符,也没有对此修饰符链的引用。

标签: swiftgenericsswiftuiviewmodifier

解决方案


TabItemView是一个结构有两个关联的类型。使用时必须指定具体类型。有点像as? TabItemView<Text, Color>...... 然而,不可能指定一个不透明的类型(View)。所以我的建议是:

TabItemView将's更改contentAnyView并保持tabItem's 类型与tabItems's 类型相同。


推荐阅读