当用作函数中的参数时,swift闭包是否可以设置为默认值?

Eri*_*ric 38 macos ios swift

Swift函数的一个非常方便的功能是函数参数可以具有默认值:

func someFunction(parameterWithDefault: Int = 42) {
    //if no arguments are passed to the function call,
    //value of parameterWithDefault is 42
}
Run Code Online (Sandbox Code Playgroud)

如果参数是闭包,有没有办法让它有一个默认值?请参阅以下示例:

func sendBody(
    body: NSData? = nil,
    success: (data: NSData) -> Void,
    failure: (data: NSData?) -> Void) {
}
Run Code Online (Sandbox Code Playgroud)

有没有办法不强制开发人员为调用successfailure调用时传递值sendBody

Air*_*ity 34

是的,函数只是您的值,因此您可以将它们作为默认值提供:

// just to show you can do it with inline closures or regular functions
func doNothing<T>(t: T) -> Void { }

func sendBody(
    body: NSData? = nil,
    success: (data: NSData) -> Void = { _ in return },
    failure: (data: NSData?) -> Void = doNothing
)
{  }
Run Code Online (Sandbox Code Playgroud)

或者,您可以将它们设为可选,这样您就可以检测调用者是否通过了一个:

func sendBody(
    body: NSData? = nil,
    success: ((NSData) -> Void)? = nil,
    failure: ((NSData?) -> Void)? = nil
    )
{ success?(NSData()) }

sendBody(success: { _ in print("ah, yeah!") })
Run Code Online (Sandbox Code Playgroud)

另外值得注意的是,如果你这样做:如果调用者使用尾随闭包语法,这将是参数列表中的最后一个闭包.所以你希望最后一个是用户最想要提供的那个,这可能是成功的关闭:

func sendBody(
    body: NSData? = nil,
    success: ((NSData) -> Void)? = nil,
    failure: ((NSData?) -> Void)? = nil
    )
{
    if success != nil { print("passed a success closure") }
    if failure != nil { print("passed a failure closure") }
}

// this prints "passed a failure closure"
sendBody { data in
    print("which closure is this?")
}
Run Code Online (Sandbox Code Playgroud)

除此之外,函数声明中的顺序与调用者无关 - 可以按任何顺序提供默认参数.


San*_*eep 5

你可以这样做,

let defaultSuccess: NSData -> Void = {
    (data: NSData) in

}

let defaultFailure: NSData? -> Void = {
    (data: NSData?) in
}

func sendBody( body: NSData? = nil, success: (data: NSData) -> Void = defaultSuccess, failure: (data: NSData?) -> Void = defaultFailure) {
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以调用其中一种方法.注意使用默认参数调用的sendBody.

sendBody()
sendBody(body: , success: , failure: )
Run Code Online (Sandbox Code Playgroud)

您也可以调用所有变体,例如只传递上述方法中的一个参数,因为您必须使用命名参数调用它.

sendBody()
sendBody(body:)

sendBody(failure: )
sendBody(success:)

sendBody(body: , success: , failure: )
Run Code Online (Sandbox Code Playgroud)


spn*_*nkr 5

如何为函数参数设置默认值。适用于 Swift 4 和 5、Xcode 13 和 14。

func someFunction(age: Int, doSomething: @escaping () -> Void = {}){
  //do work here
  
  doSomething()
}
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做

someFunction(age: 18) {
  print("hello")
}

someFunction(age: 19)
Run Code Online (Sandbox Code Playgroud)

您可能需要也可能不需要使用该@escaping关键字。如果您需要,Xcode 会在构建时向您发出警告。

基本上,如果您的函数更改外部变量,您需要使用@escaping. 请参阅Swift @escaping 和 Completion Handler来了解这一点。