【问题标题】:SwiftUI: Creating custom alertSwiftUI:创建自定义警报
【发布时间】:2021-06-29 11:55:28
【问题描述】:

我正在尝试抽象出一个在我的应用程序的多个地方使用的警报。

我复制并粘贴了func alert(isPresented: Binding<Bool>, content: () -> Alert) -> some View 的实现并对其进行了调整以适应我的使用:

extension View {
    func externalURLAlert(isPresented: Binding<Bool>, action: ()) -> some View {
        isPresented.wrappedValue ? AnyView(Alert(
            title: Text("alert.externalURL.title".localized),
            message: Text("alert.externalURL.message".localized),
            primaryButton: .cancel(),
            secondaryButton: .default(Text("alert.externalURL.openAction.title".localized)) {
                action
            }
        )) : AnyView(EmptyView())
    }
}

我的计划是在像 .externalURLAlert(isPresented: $isPresented, action: someAction) 这样的视图上调用它,但我无法编译该函数。

我得到的错误如下:

Initializer 'init(_:)' 要求 'Alert' 符合 'View'

【问题讨论】:

    标签: ios xcode swiftui


    【解决方案1】:

    修饰符的工作方式是返回调用它们的视图的修改版本。如果您调用Text("").foregroundColor(...),您会收到一个带有新前景色的新Text 视图。警报也是如此,如果您调用Text("").alert(...,您会收到一个Text 视图,该视图可以在顶部显示警报。

    另一方面,您的修饰符会完全删除该层次结构并将其替换为空视图或警报,但此警报没有关于应在何处显示的信息。

    如果您想要显示一个标准化的警报,您应该利用现有的修饰符和您自己的参数,如下所示:

    extension View {
        func externalURLAlert(isPresented: Binding<Bool>, action: ()) -> some View {
            self.alert(isPresented: isPresented) {
                Alert(
                    title: Text("alert.externalURL.title".localized),
                    message: Text("alert.externalURL.message".localized),
                    primaryButton: .cancel(),
                    secondaryButton: .default(Text("alert.externalURL.openAction.title".localized)) {
                        action()
                    }
                )
            }
        }
    }
    

    注意self 的使用,因为我们想要维护层次结构,而.alert(...) 因为我们正在使用已经知道如何显示警报的现有系统修饰符。

    【讨论】:

      【解决方案2】:

      尝试以下方法:

      extension View {
      
          @ViewBuilder
          func externalURLAlert(isPresented: Binding<Bool>, action: ()) -> some View {
             if isPresented.wrappedValue {
                 Alert(
                    title: Text("alert.externalURL.title".localized),
                    message: Text("alert.externalURL.message".localized),
                    primaryButton: .cancel(),
                    secondaryButton: .default(Text("alert.externalURL.openAction.title".localized)) { action }
                 )
            }
      
      }
      

      加上错误中写的你需要使Alert符合View。

      还可以尝试使用 .sheet() -- 这看起来像您在搜索。

      使用示例:https://www.hackingwithswift.com/quick-start/swiftui/how-to-present-a-new-view-using-sheets

      或您通过 google 找到的任何内容 -> "swiftUI usage .sheet"

      【讨论】:

      • 这不起作用,因为您只是替换现有的层次结构。例如,如果您在 NavigationView 上调用它,结果是 EmptyViewAlert,但 NavigationView 消失了。
      • @EmilioPelaez 我只是展示了如何以正确的方式编写他的代码。那么主要问题呢? sheet() 将按他的预期工作。我在我的回答中写了关于工作表的内容。
      • 如果它不编译(因为Alert 不符合View)并且不起作用(因为即使它这样做了,因为我已经说,你正在清除视图层次结构)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-01
      • 1970-01-01
      • 2020-06-27
      • 2017-11-16
      • 1970-01-01
      相关资源
      最近更新 更多