【问题标题】:Use Combine to route SwiftUI Views使用 Combine 路由 SwiftUI 视图
【发布时间】:2021-08-21 13:20:03
【问题描述】:

我正在尝试使用 Combine 来路由 SwiftUI 视图,它有点工作,但有一些不需要的行为,我希望有人可以帮助我。我制作了一个example project,它只包含两个文件,ViewRouter.swiftViewController.swift,它只包含一个@IBSegueAction,以返回一个UIHostingController

ViewRouter 类是包含 @ViewBuilder 属性的 SwiftUI 视图的 ViewModel。当SwiftUI 视图调用didFinish() 函数时,step 属性设置为下一个View

class ViewRouter: ObservableObject {
    enum Step { case test1, test2, test3, test4 }
    @Published var step: Step = .test1
    @ViewBuilder var nextStepView: some View {
        switch step {
        case .test1:
            Test1(router: self)
        case .test2:
            Test2(router: self)
        case .test3:
            Test3(router: self)
        case .test4:
            Test4(router: self)
        }
    }
    
    func didFinish() {
        switch step {
        case .test1:
            step = .test2
        case .test2:
            step = .test3
        case .test3:
            step = .test4
        case .test4:
            break
        }
    }
}

这非常适合Test1,当点击Next 链接时,Test1 视图会向左移动,以显示Test2。然而,当在Test2 中点击Next 时,Test2 向左移动以显示Test3,但随后它立即向右侧移动以显示相同的Test3 视图。在Test3 中点击Next 时会发生完全相同的情况。

点击后退按钮总是以Test1 视图结束。

所有四个视图都是一样的,除了Text中的文字:

struct Test1: View {
    @ObservedObject var router: ViewRouter
    @State var nextView = false

    var body: some View {
        VStack {
            NavigationLink(destination: router.nextStepView, isActive: $nextView) {
                EmptyView()
            }

            Text("Test1")
            
            Button(action: {
                nextView = true
                router.didFinish()
            }, label: {
                Text("Next")
            })
        }
    }
}

【问题讨论】:

标签: swift swiftui combine


【解决方案1】:

我对 ViewRouter 类做了一些小改动来完成这项工作。我得出的结论是,所有 SwiftUI 视图都需要它们自己的 ViewRouter 实例。对所有视图使用相同的 ViewRouter 共享实例会导致不需要的行为。我引入了一个nextStep 可选属性,当视图调用didFinish 函数时设置为当前步骤,以确保路由器在第二次或第三次调用时返回正确的nextStepView

我已将更新推送到示例 Xcode 项目的 GitHub 存储库。

修改后的类现在看起来像这样:

class ViewRouter: ObservableObject {
    enum Step { case test1, test2, test3, test4 }
    @Published var step: Step
    private var nextStep: Step?
    @ViewBuilder var nextStepView: some View {
        switch step {
        case .test1:
            Test1(router: self)
        case .test2:
            Test2(router: ViewRouter(step: .test2))
        case .test3:
            Test3(router: ViewRouter(step: .test3))
        case .test4:
            Test4(router: ViewRouter(step: .test4))
        }
    }
    
    init(step: Step) {
        self.step = step
    }
    
    func didFinish() {
        switch step {
        case .test1:
            if let next = nextStep {
                step = next
            } else {
                step = .test2
                nextStep = .test2
            }
        case .test2:
            if let next = nextStep {
                step = next
            } else {
                step = .test3
                nextStep = .test3
            }
        case .test3:
            if let next = nextStep {
                step = next
            } else {
                step = .test4
                nextStep = .test4
            }
        case .test4:
            break
        }
    }
    
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-16
    • 2021-06-16
    • 1970-01-01
    • 2020-06-10
    • 2020-01-21
    • 1970-01-01
    • 2017-08-22
    • 2020-02-02
    相关资源
    最近更新 更多