繁体   English   中英

如何在基于 SwiftUI 的 iOS 应用程序中呈现连续视图?

[英]How can I present successive views in a SwiftUI-based iOS app?

在尝试学习 SwiftUI 时,我正在开发一个 iOS 应用程序,该应用程序显示“观察会话”的列表视图,并允许用户从“新建”按钮创建新会话。 它需要一个中间步骤来选择新的 session 将基于的配置。

我能够显示合理的 session 列表和配置列表屏幕,但我处理所选配置的尝试失败了。

发送到配置列表屏幕的闭包被成功调用,打印语句正确显示配置名称就证明了这一点。 但是应该呈现第三种视图类型的处理程序的其余部分无法工作(即它不呈现视图)。 此外,我收到一条警告,我试图展示“未使用 'sheet(isPresented:onDismiss:content:)' 的调用结果”的新视图。 我希望有人可以向我解释我做错了什么。 这是在 Xcode 12.3 中,针对模拟器中的 iOS 14。 这是显示问题的 SessionListView 代码:

import SwiftUI

struct SessionsListView: View {
    @ObservedObject var dataManager: DataManager
    @State private var isPresented = false
    @State private var isObserving = false
    var body: some View {
        VStack {
            List {
                ForEach(dataManager.allSavedSessions) {session in
                    NavigationLink(
                        // Navigate to a detail view
                        destination: SessionDetailView(session: session),
                        label: {
                            Text("\(session.name)")
                        })
                }
            }
            Spacer()
            Button("New Session") {
                isPresented = true
            }
            .padding()
            .font(.headline)
            .sheet(isPresented: $isPresented) {
                // Present a configuration list view where user must select configuration to use for new session
                // Requires a closure that's called upon selection in the configuration list view, to handle the selection
                NavigationView {
                    ConfigurationsListView(dataManager: dataManager, selectionHandler: { config in
                        isPresented = false
                        isObserving = true
                        handleConfigSelection(config)
                    })
                    .navigationTitle("Configurations")
                    .navigationBarItems(trailing: Button("Cancel") {
                        isPresented = false
                    })
                }
            }
        }
    }
        
    private func handleConfigSelection(_ config: SessionConfiguration) {
        // Use the selected configuration to start an observations session
        print("Selected \(config.name). Will attempt to show sheet from \(self)")
        isPresented = false
        isObserving = true
        self.sheet(isPresented: $isObserving) { // displaying warning: "Result of call to 'sheet(isPresented:onDismiss:content:)' is unused"
            NavigationView {
                ObservationsView(configuration: config)
                    .navigationBarItems(trailing: Button(action: {}) {
                        Text("Done")
                    })
            }
        }
    }
}

这是我在此简化演示中使用的 model 类型的代码。

观察会话:


struct ObservationSession: Identifiable {
    let id: UUID = UUID()
    let name: String
}

会话配置:

import Foundation

struct ObservationSession: Identifiable {
    let id: UUID = UUID()
    let name: String
}

数据管理器:

import Foundation

class DataManager: ObservableObject {
    var allSavedSessions: [ObservationSession] {
        return [ObservationSession(name: "Field mouse droppings"), ObservationSession(name: "Squirrels running up trees"), ObservationSession(name: "Squirrel behavior in urban landscapes")]
    }
    
    var allSavedConfigurations: [SessionConfiguration] {
        return [SessionConfiguration(name: "Squirrel Behavior"), SessionConfiguration(name: "Squirrel/Tree Interaction"), SessionConfiguration(name: "Mouse Behavior")]
    }
}

经过一夜的睡眠后,我想出了一种似乎可行的方法。

我在 SessionConfiguration 类型的 DataManager class 中添加了“currentConfiguration”属性,并在用户从列表中选择配置时在 ConfigurationsListView 中设置该属性。 然后 SessionsListView 可以显示 ConfigurationsListView 或 ObservationsView ,具体取决于跟踪流的变量:

import SwiftUI

enum SessionListPresentationFlow {
    case configuration
    case observation
}

struct SessionsListView: View {
    @ObservedObject var dataManager: DataManager
    @State private var isPresented = false
    @State var flow: SessionListPresentationFlow = .configuration
    var body: some View {
        VStack {
            List {
                ForEach(dataManager.allSavedSessions) {session in
                    NavigationLink(
                        // Navigate to a detail view
                        destination: SessionDetailView(session: session),
                        label: {
                            Text("\(session.name)")
                        })
                }
            }
            Spacer()
            Button("New Session") {
                isPresented = true
            }
            .padding()
            .font(.headline)
            .sheet(isPresented: $isPresented, onDismiss: {
                if flow == .observation {
                    flow = .configuration
                } else {
                    flow = .configuration
                }
                dataManager.currentConfiguration = nil
                isPresented = false
            }) {
                // Present a view for the appropriate flow
                viewForCurrentFlow()
            }
        }
    }
    
    @ViewBuilder private func viewForCurrentFlow() -> some View {
        if flow == .configuration {
            NavigationView {
                ConfigurationsListView(dataManager: dataManager, selectionHandler: { config in
                    isPresented = false
                    handleConfigSelection(config)
                })
                .navigationTitle("Configurations")
                .navigationBarItems(trailing: Button("Cancel") {
                    isPresented = false
                    flow = .observation
                })
            }
        } else if flow == .observation, let config = dataManager.currentConfiguration {
            NavigationView {
                ObservationsView(configuration: config)
                    .navigationBarItems(leading: Button(action: {isPresented = false}) {
                        Text("Done")
                    })
            }
        } else {
            EmptyView()
        }
    }
    
    private func handleConfigSelection(_ config: SessionConfiguration) {
        flow = .observation
        isPresented = true
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM