如何在 SwiftUI 中实现自定义回调操作?类似于 onAppear 功能

Ram*_*mis 3 swift swiftui

我有带有两个按钮的自定义ActionView : CarBike。当点击这些按钮时,我需要在MainView修改器中触发onCarTap / onBikeTap 。

我当前的实现是错误的:

  • 传递给不带参数的调用的参数
  • 元组类型“Void”的值没有成员“onBikeTap”

源代码:

struct ActionView: View {
    // Callback for button taps
    var onCarTap: (() -> Void)?
    var onBikeTap: (() -> Void)?
    
    var body: some View {
        HStack {
            Button(action: {
                onCarTap?()
            }, label: {
                Text("Car")
            })
            Button(action: {
                onBikeTap?()
            }, label: {
                Text("Bike")
            })
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在寻找这样的解决方案:

struct MainView: View {
    var body: some View {
        ActionView()
            .onCarTap({})
            .onBikeTap({ })
    }
}
Run Code Online (Sandbox Code Playgroud)

可以这样实现:

    ActionView(onCarTap: {
        print("on car tap")
    }, onBikeTap: {
        print("on bike tap")
    })
Run Code Online (Sandbox Code Playgroud)

paw*_*222 6

假设您有以下视图:

struct ActionView: View {
    var onCarTapAction: (() -> Void)?
    var onBikeTapAction: (() -> Void)?

    var body: some View {
        HStack {
            Button(action: {
                onCarTapAction?()
            }, label: {
                Text("Car")
            })
            Button(action: {
                onBikeTapAction?()
            }, label: {
                Text("Bike")
            })
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以创建一个扩展:

extension ActionView {
    func onCarTap(action: @escaping (() -> Void)) -> ActionView {
        ActionView(onCarTapAction: action, onBikeTapAction: onBikeTapAction)
    }

    func onBikeTap(action: @escaping (() -> Void)) -> ActionView {
        ActionView(onCarTapAction: onCarTapAction, onBikeTapAction: action)
    }
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

struct ContentView: View {
    var body: some View {
        ActionView()
            .onCarTap {
                print("onCarTap")
            }
            .onBikeTap {
                print("onBikeTap")
            }
    }
}
Run Code Online (Sandbox Code Playgroud)


Kyo*_*ang 5

您可以根据您的目的声明一个修饰符,如下所示。

extension ActionView {
    func onCarTap(_ handler: @escaping () -> Void) -> ActionView {
        var new = self
        new.onCarTap = handler
        return new
    }
}
Run Code Online (Sandbox Code Playgroud)

此外,如果您希望隐藏处理程序属性privatefileprivate防止直接访问它,则必须声明一个指定的init属性,它接受除处理程序之外的属性参数。