SwiftUI MVVM协调器/路由器/ NavigationLink

我在将UIKit架构模式转换为SwiftUI时遇到问题。我

目前的模式主要是带有协调器/路由器的MVVM。通过

添加@ ObservableObject / @ Published ,MVVM部分看起来非常简单自然。但是

,协调/路由似乎并不直观。视图和协调

(导航)功能在SwiftUI中紧密结合在一起。似乎

实际上不可能通过使用helper结构将它们分开

AnyView。

这里是一个示例:我想在SwiftUI中创建可重用的行/单元。可以说

生产中的这一行非常复杂,因此我想重用它。我也

希望将其放置在另一个模块中,以便可以在多个目标中重复使用它。

(例如iOS,macCatalyst等)

在此处输入图片说明

现在,我想控制当用户点击该视图或该视图中的按钮时发生的情况

。根据上下文,我需要导航到不同的

目的地。据我所看到的可能NavigationLink目标必须

要么硬连线到视图或AnyView已被传递到

视图。

这里有一些示例代码。该单元格/行包含两个按钮。我想导航

到其他依赖于上下文的视图,而不要硬连接

到代码中:

struct ProductFamilyRow: View {

@State private var selection: Int? = 0

let item: ProductFamilyItem

let destinationView1: AnyView

let destinationView2: AnyView

var body: some View {

VStack {

NavigationLink(

destination: destinationView1,

tag: 1,

selection: self.$selection

) {

EmptyView()

}

NavigationLink(

destination: destinationView2,

tag: 2,

selection: self.$selection

) {

EmptyView()

}

HStack {

Text(item.title)

Button("Destination 1") {

self.selection = 1

}.foregroundColor(Color.blue)

Button("Destination 2") {

self.selection = 2

}.foregroundColor(Color.blue)

}

//Image(item.image)

}.buttonStyle(PlainButtonStyle())

}

}

这似乎是SwiftUI中的主要设计缺陷。

除了使用AnyView

hack 之外,带有导航链接的可重用组件基本上是不可能的。据我所知AnyView,它只用于

需要类型擦除的特定用例,并且在性能上有很多缺点。因此,我不

认为这是使用SwiftUI创建可重用,可导航视图的惯用解决方案

这真的是唯一的解决方案吗?也许我完全错了,这始终是

错误的方向。我读过某处(找不到该帖子..)有关

使用某种中央状态的信息,该状态指示了要显示的视图,但是我没有看到

具体的示例如何执行此操作。

第二个挑战:我也不希望单元格对其他任何轻按然后对

按钮做出反应。但是似乎无法控制

如果点击该单元格导航到的位置。(因此,请不要点击按钮之一,而要在

单元格中的任何位置)在当前示例代码中,它(出于任何原因)导航至

“目标2”。

提前致谢。

回答:

最好在行中使用泛型,如下所示(已通过Xcode 11.4测试)

用法示例:

ProductFamilyRow(item: ProductFamilyItem(title: "Test"),

destinationView1: { Text("Details1") },

destinationView2: { Text("Details2") })

接口:

更新 -为行突出显示添加了块。列表自动检测

行内的按钮或链接,并突出显示是否存在任何标准(!键)。因此,

要禁用此类行为,需要将所有内容隐藏在自定义按钮

样式下。

struct ProductFamilyRowStyle: ButtonStyle {

func makeBody(configuration: Self.Configuration) -> some View {

configuration.label

.colorMultiply(configuration.isPressed ?

Color.white.opacity(0.5) : Color.white) // any effect you want

}

}

struct ProductFamilyRow<D1: View, D2: View>: View {

let item: ProductFamilyItem

let destinationView1: () -> D1

let destinationView2: () -> D2

init(item: ProductFamilyItem, @ViewBuilder destinationView1: @escaping () -> D1,

@ViewBuilder destinationView2: @escaping () -> D2)

{

self.item = item

self.destinationView1 = destinationView1

self.destinationView2 = destinationView2

}

@State private var selection: Int? = 0

var body: some View {

VStack {

HStack {

Text(item.title)

Button(action: {

self.selection = 1

}) {

Text("Destination 1")

.background( // hide link inside button !!

NavigationLink(destination: destinationView1(),

tag: 1, selection: self.$selection) { EmptyView() }

)

}.foregroundColor(Color.blue)

Button(action: {

self.selection = 2

}) {

Text("Destination 2")

.background(

NavigationLink(destination: destinationView2(),

tag: 2, selection: self.$selection) { EmptyView() }

)

}.foregroundColor(Color.blue)

}

//Image(item.image)

}.frame(maxWidth: .infinity) // to have container centered

.buttonStyle(ProductFamilyRowStyle())

}

}

以上是 SwiftUI MVVM协调器/路由器/ NavigationLink 的全部内容, 来源链接: utcz.com/qa/408868.html

回到顶部