将带有参数的闭包传递给 SwiftUI 视图

jon*_*ham 2 swift

我正在开发一个 SwiftUI 项目。我创建了一个自定义按钮,可以向其传递函数。这看起来如下所示。

自定义按钮

struct CustomButton: View {
    let buttonTitle: String
    var function: () -> Void
    
    var body: some View {
        Button(action: {
            self.function()
        }, label: {
            Text(self.buttonTitle)
        }) // Button - Login
    } // View
}
Run Code Online (Sandbox Code Playgroud)

在使用它的视图中,我可以执行以下操作。

struct NewView: View {
    var body: some View {
        CustomButton(buttonTitle: "Custom Button", function: myFunc)
    }
}

func myFunc() {
    print("My Custom Button Tapped")
}
Run Code Online (Sandbox Code Playgroud)

这确实有效。

我现在想做的是将参数传递给函数。我在这方面遇到了麻烦。我尝试了以下方法。

struct CustomButton: View {
    let buttonTitle: String
    var function: (String) -> Void
    
    var body: some View {
        Button(action: {
            self.function() // I DON'T KNOW WHAT DO TO HERE.
        }, label: {
            Text(self.buttonTitle)
        }) // Button - Login
    } // View
}

struct NewView: View {
    var body: some View {
        CustomButton(buttonTitle: "Custom Button", function: myFunc(text: "Hello"))
    }
}

func myFunc(text: String) {
    print(text)
}
Run Code Online (Sandbox Code Playgroud)

这是行不通的。当我调用 CustomButton 时,出现以下错误。

无法将类型“()”的值转换为预期参数类型“() -> Void”

我也不知道要在 Button 操作中的 self.function() 调用中添加什么参数。

任何帮助将不胜感激。

jn_*_*pdx 5

首先,最简单的答案 - 通过将myFunc(text: "Hello")in括起来{ },您可以将其变成闭包。然后,它可以传递到您的原始() -> Void声明。

struct CustomButton: View {
    let buttonTitle: String
    let function : () -> Void
    
    var body: some View {
        Button(action: {
            self.function()
        }, label: {
            Text(self.buttonTitle)
        }) // Button - Login
    } // View
}

struct NewView: View {
    var body: some View {
        CustomButton(buttonTitle: "Custom Button", function: {
            myFunc(text: "Hello")
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

您也可以使用@autoclosure来提供类似的行为而不使用{ },但您必须init为您的声明一个自定义CustomButton:

struct CustomButton: View {
    let buttonTitle: String
    let function : () -> Void
    
    init(buttonTitle: String, function: @autoclosure @escaping () -> Void) {
        self.buttonTitle = buttonTitle
        self.function = function
    }
    
    var body: some View {
        Button(action: {
            self.function()
        }, label: {
            Text(self.buttonTitle)
        }) // Button - Login
    } // View
}

struct NewView: View {
    var body: some View {
        CustomButton(buttonTitle: "Custom Button", function: myFunc(text:"Hello"))
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,另一种选择(我认为不太可能有用例,但以防万一)是单独传递字符串参数:

struct CustomButton: View {
    let buttonTitle: String
    let stringParameter : String
    let function : (String) -> Void
    
    var body: some View {
        Button(action: {
            self.function(stringParameter)
        }, label: {
            Text(self.buttonTitle)
        }) // Button - Login
    } // View
}

struct NewView: View {
    var body: some View {
        CustomButton(buttonTitle: "Custom Button", stringParameter: "Hello", function: myFunc)
    }
}
Run Code Online (Sandbox Code Playgroud)