首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何避免在SwiftUI中的回调闭包中使用“`AnyView`”类型擦除?

如何避免在SwiftUI中的回调闭包中使用“`AnyView`”类型擦除?
EN

Stack Overflow用户
提问于 2022-02-09 05:12:20
回答 1查看 215关注 0票数 1

我正在尝试创建基于ListScrollView的表视图,其中包含一个共享的基本视图。我目前的尝试使用了基于构建器的方法,但需要使用AnyView类型擦除的闭包。

我的目标是避免使用AnyView类型擦除,以提高性能、可伸缩性和设计。

到目前为止,我使用泛型参数重新设计的尝试都失败了。

下面的简化(和工作)代码示例只显示一个String列,但是捕捉到了基本的挑战。(实际上,这些是多列表,具有不同的数据类型、专门的格式化程序、修饰符等)

代码语言:javascript
复制
import SwiftUI

struct ContentView: View {
    let data = ["a", "b", "c", "d"]
    var body: some View {
        HStack {
            ListTable(title: "My List", data: data)
            ScrollTable(title: "My Scroll", data: data)
        }
    }
}

struct ListTable<T: Hashable>: View {
    var title: String, data: [T]
    var body: some View {
        BaseTable() { header, row in
            VStack {
                header(title)
                List(data, id: \.self) { row($0) }
            }
        }
    }
}

struct ScrollTable<T: Hashable>: View {
    var title: String, data: [T]
    var body: some View {
        BaseTable() { header, row in
            VStack {
                header(title)
                ScrollView { ForEach(data, id: \.self) { row($0) } }
            }
        }
    }
}

struct BaseTable<Content: View, T: Hashable>: View {
    typealias HBuilder = (String) -> AnyView
    typealias RBuilder = (T) -> AnyView
    var builder: (@escaping HBuilder, @escaping RBuilder) -> Content
    var body: some View {
        // NOTE this is where I'd like to avoid type-erasure to AnyView
        builder({ AnyView( Text("Header \($0)") )},
                { AnyView( Text("Row \(String(describing: $0))") ) })
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View { ContentView() }
}

两个相关的问题没有提供很好的解决办法:

  • 65810765 -如何创建带有输入的闭包结构参数,在SwiftUI?
  • 64655195中返回some View而不是AnyView --如何避免将SwiftUI视图作为参数传递给AnyView?
EN

回答 1

Stack Overflow用户

发布于 2022-02-09 17:00:18

我对我自己的问题有一个很好的答案。

为行创建一个“包装器”视图,它将服务于行生成器闭包中使用的显式类型:

代码语言:javascript
复制
// new 'wrapper' view, which can contain Text, LazyVGrid, etc.
struct RowView<T: Hashable>: View {
    var value: T
    var body: some View {
        Text("Row \(String(describing: value))")
    }
}

// update to original BaseTable
struct BaseTable<Content: View, T: Hashable>: View {
    typealias HBuilder = (String) -> Text
    typealias RBuilder = (T) -> RowView<T>
    var builder: (@escaping HBuilder, @escaping RBuilder) -> Content
    var body: some View {
        builder({ Text("Header \($0)") },
                { RowView<T>(value: $0) })
    }
}

感谢评论员们!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71044305

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档