ios - 在 SwiftUI 中传递视图或高阶组件
问题描述
作为一个了解 React 的人,来到 SwiftUI 之后,我在寻找合适的抽象方面遇到了挑战。这是一个例子,但我的问题更笼统。它与传递视图或 React 社区所称的高阶组件有关。我的例子如下。TLDR:如何在下面的列表视图中抽象和删除重复项?
一些模型(这些最终会有所不同):
struct Apple: Comparable, Identifiable {
let id: UUID = UUID()
let label: String
static func < (lhs: Apple, rhs: Apple) -> Bool {
lhs.label < rhs.label
}
}
struct Banana: Comparable, Identifiable {
let id: UUID = UUID()
let label: String
static func < (lhs: Banana, rhs: Banana) -> Bool {
lhs.label < rhs.label
}
}
一些基本的细节视图(最终会有所不同):
struct AppleView: View {
let apple: Apple
var body: some View {
Text(apple.label)
}
}
struct BananaView: View {
let banana: Banana
var body: some View {
Text(banana.label)
}
}
还有两个有很多重复的列表视图:
struct AppleListView: View {
let title: String
let apples: [Apple]
var body: some View {
List(apples.sorted()) { apple in
NavigationLink(destination: AppleView(apple: apple)) {
Text(apple.label)
.padding(.all)
}
}
.navigationBarTitle(Text(title), displayMode: .inline)
}
}
struct BananaListView: View {
let title: String
let bananas: [Banana]
var body: some View {
List(bananas.sorted()) { banana in
NavigationLink(destination: BananaView(banana: banana))
Text(banana.label)
.padding(.all)
}
}
.navigationBarTitle(Text(title), displayMode: .inline)
}
}
如您所见,它仅在很小的部分上有所不同。集合的类型和destination
视图不同。destination
当涉及到这个视图时,我想保持灵活性,因为Apple
和Banana
以及它们上面的详细视图最终会有所不同。此外,我可能想Cherry
稍后再添加,所以抽象这个列表视图是有价值的。
所以,我的问题是:我怎样才能最好地抽象上面的列表视图并删除其中的重复项?你有什么建议?我的尝试如下,但它给我留下了类型错误。它涉及前面提到的高阶组件思想。
我对类型错误的尝试:
struct AppleListView: View {
let title: String
let apples: [Apple]
var body: some View {
ListView(
title: title,
rows: apples, // it complains about types here -> `Cannot convert value of type '[Apple]' to expected argument type 'Array<_>'`
rowView: { apple in Text(apple.label) },
destinationView: { apple in AppleView(apple: apple) }
)
}
}
struct BananaListView: View {
let title: String
let bananas: [Banana]
var body: some View {
ListView(
title: title,
rows: bananas, // it complains about types here -> `Cannot convert value of type '[Banana]' to expected argument type 'Array<_>'`
rowView: { banana in Text(banana.label) },
destinationView: { banana in BananaView(banana: banana) }
)
}
}
struct ListView<Content: View, Row: Comparable & Identifiable>: View {
let title: String
let rows: [Row]
let rowView: (Row) -> Content
let destinationView: (Row) -> Content
var body: some View {
List(rows.sorted()) { row in
NavigationLink(destination: self.destinationView(row)) {
self.rowView(row)
.padding(.all)
}
}
.navigationBarTitle(Text(title), displayMode: .inline)
}
}
解决方案
这是因为你为标签和目的地做了相同的类型,这里是固定的变体
struct ListView<Target: View, Label: View, Row: Comparable & Identifiable>: View {
let title: String
let rows: [Row]
let rowView: (Row) -> Label
let destinationView: (Row) -> Target
var body: some View {
List(rows.sorted()) { row in
NavigationLink(destination: self.destinationView(row)) {
self.rowView(row)
.padding(.all)
}
}
.navigationBarTitle(Text(title), displayMode: .inline)
}
}
推荐阅读
- lotus-domino - 由于 MIME 类型不匹配 Domino 10.0.4,javascript 被阻止
- model - 创建域模型
- c++ - 为什么D2D绘图在D3D11下?
- php - 我正在尝试通过 localhost(XAMPP)在 php 中使用邮件功能发送电子邮件,但是电子邮件没有发送。我如何实现它?
- python - 试图在我的 matplotlib 图/该图的基础数据上获取峰值点标签
- react-native - 我们如何自定义 react-native-cn-richtext-editor 的工具栏以在其上添加按钮
- javascript - Expo Location.startLocationUpdatesAsync 后台服务在真实设备上不起作用(ios,android)
- reactjs - 在没有 webpack-dev-server 的情况下手动设置电子反应
- machine-learning - 文本分类:LSTM 与前馈
- r - 将代码推送到 github 时自动更新 R 文档、NAMESPACE 和DESCRIPTION 文件