【问题标题】:SwiftUI: Close modal sheet programmatically from a function inside an Environment ObjectSwiftUI:从环境对象内的函数以编程方式关闭模式表
【发布时间】:2021-11-29 02:05:21
【问题描述】:

我有一个显示模式表的主视图。由于我有多个模态,我使用枚举和状态来控制which sheet is presented.

@State var activeSheet: Sheet?

在我的主视图中:

    Button(action: {
        activeSheet = .settings
    }, label: {
        Text(“Button”)
    })

   .sheet(item: $activeSheet) { sheet in
        switch sheet {
        case .info:
          InfoView()
        case .settings:
          SettingsView()
        }
      }

设置视图:

struct SettingsView: View {
    @Environment(\.presentationMode) private var presentationMode
    @EnvironmentObject var model: MainModel
    
    var body: some View {
        Button("Action") {
            model.myFunction()
        }
    }
}

在我的 InfoView 表中,我有一个按钮,可以调用 EnvironmentObject 中的函数。 EnvironmentObject 中的功能完成后如何关闭工作表?

每个视图都链接到同一个 EnvironmentObject 顺便说一句。

谢谢!

【问题讨论】:

  • ImageSizeImageSizead

标签: ios swift swiftui environmentobject modal-view


【解决方案1】:

根据您部署的最低 iOS 版本,您有两种选择:

如果您的最低 iOS 版本为 InfoView 和 SettingsView 中都使用系统环境 \.presentationMode

struct SettingsView: View {
    @EnvironmentObject var model: MainModel
    @Environment(\.presentationMode) private var presentationMode

    var body: some View {
        Button("Dismiss") {

            /// ... Do something here prior to dismissing the sheet.
            model.MyFunction(email: email, password: password) {
                presentationMode.wrappedValue.dismiss()
            }
        }
    }
}

在您的最低 iOS 版本为 iOS 15 时,InfoViewSettingsView 都使用系统环境 \.dismiss

struct SettingsView: View {
    @EnvironmentObject var model: MainModel
    @Environment(\.dismiss) private var dismiss

    var body: some View {
        Button("Dismiss") {

            /// ... Do something here prior to dismissing the sheet.
            model.MyFunction(email: email, password: password) {
                dismiss()
            }
        }
    }
}

还有MainModel类:

class MainModel: ObservableObject {
    func myFunction(email: String, password: String, onSuccess: (() -> Void)? = nil) {         
        auth.signIn(withEmail: email, password: password) { [weak self] result, error in
            if result == nil, error != nil {
                 self?.showAlert = true
            } else {
                 guard result != nil, error == nil else { return }
                 /* Success */
                 self?.signedIn = true
                 onSuccess?()
            }
        }
    }
}

替代解决方案:

如果您的最低部署目标是 >= iOS 14,您可以像这样监听环境对象属性的变化:

struct SettingsView: View {
    @EnvironmentObject var model: MainModel
    @Environment(\.dismiss) private var dismiss

    var body: some View {
        Button("Dismiss") {
            model.MyFunction(email: email, password: password)
        }
        .onChange(of: model.signedIn) { signedIn in
            if signedIn {
                dismiss()
            }
        }
    }
}

【讨论】:

  • 感谢您的回复!但是,在我的情况下,我只想在 EnvironmentObject 的功能完成后关闭工作表。 struct SettingsView: View { @EnvironmentObject var model: MainModel var body: some View { Button("Action") { model.MyFunction() } } } 我该怎么做?
  • 什么是model.MyFunction()?如果是同步函数,则在调用model.MyFunction() 后调用dismiss()。如果它是异步函数,那么您必须知道它何时完成。 IE。您必须有一个完成处理程序作为参数。你有吗?
  • 这里是函数。如果函数返回错误,模态视图应保持打开状态,如果成功,则模态视图应关闭。 func myFunction(email: String, password: String) { auth.signIn(withEmail: email, password: password) { [weak self] 结果, if result == nil, error != nil { self?.showAlert = true } else { guard result != nil, error == nil else { return } /* 成功 */ self?.signedIn = true } } }
  • onSuccess参数添加到MyFunction如答案所示,并使用MyFunction如答案所示。
  • 现在添加了一个替代解决方案,包含有关您的模型的更多信息。看看吧。
猜你喜欢
  • 1970-01-01
  • 2020-11-05
  • 1970-01-01
  • 2012-10-16
  • 1970-01-01
  • 2020-05-24
  • 2015-10-20
  • 1970-01-01
  • 2023-03-21
相关资源
最近更新 更多