SwiftUI:创建自定义警报

Posted

技术标签:

【中文标题】SwiftUI:创建自定义警报【英文标题】:SwiftUI: Creating custom alert 【发布时间】: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'

【问题讨论】:

【参考方案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)并且不起作用(因为即使它这样做了,因为我已经说,你正在清除视图层次结构)。

以上是关于SwiftUI:创建自定义警报的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI-自定义容器

自定义警报创建致命错误:init(coder:) 尚未实现

SwiftUI 如何在其中创建带有自定义 UIViews 的列表

SwiftUI-自定义修饰符

Azure 指标警报中的自定义 Json 有效负载

如何指定将保存 SwiftUI 自定义视图的数组的类型信息