如何使用 SwiftUI 将可选函数传递给视图?

Jak*_*ith 1 swift swiftui

我正在尝试在 SwiftUI 中创建一个子视图,可以选择从父视图中获取一个函数,以便我可以在未给出操作的情况下执行逻辑,或者如果给出了操作,则可以在 ChildView 中调用操作。

当我尝试运行我的代码时,我在调用中缺少参数“action”的参数,我无法弄清楚为什么,因为我在 ChildView 中将操作标记为可选,所以如果在父视图?

我在 ChildView 的公共初始值设定项中将操作标记为 @escaping,以满足编译器在单击“修复”后添加 @escaping 的要求,但不知道为什么或是否应该这样做?

如果我不将操作标记为 @escaping,则会收到错误将非转义参数“操作”分配给公共初始值设定项中的 @escaping 闭包。

也许公共初始化程序导致了我的问题,但我需要将其包含在我的案例中,但我认为我错误地初始化了可选函数?

我怎样才能完成我想做的事情?

家长观点

struct ParentView: View {
    var body: some View {
        ChildView() // ERROR: Missing argument for parameter 'action' in call???
    }
}
Run Code Online (Sandbox Code Playgroud)

子视图

struct ChildView: View {
    
    let action: () -> ()?
    // ^ Should not have to be supplied since marked as optional??

    public init(action: @escaping () -> ()? ) {
        self.action = action
    }
    
    var body: some View {
        VStack {
            Text("Tap")
            .onTapGesture {
               if action != nil {
                   action()
               } else {
                  print("No function was given to child view")
               }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Joa*_*son 7

问题是您没有声明一个可选函数,而是一个返回可选 Void 的函数(无论它是什么:))。要使其可选,您需要将其括在括号中

let action: (() -> ())?
Run Code Online (Sandbox Code Playgroud)

并且以相同的方式更改 init,现在不再需要该action参数实际上是可选的。@escaping现在我们还可以给参数一个默认值

public init(action: (() -> ())? = nil ) {
    self.action = action
}
Run Code Online (Sandbox Code Playgroud)

这样就可以使用调用视图ChildView()

您还应该更改以下的用法action

if let action {
    action()
} ...
Run Code Online (Sandbox Code Playgroud)

  • 无关且可能是主观的,但我更喜欢“() -> Void”而不是“() -> ()” (2认同)