ios Swift闭包在函数中作为参数使用时可以设置为默认值吗?

kkih6yb8  于 2023-04-13  发布在  iOS
关注(0)|答案(4)|浏览(150)

Swift函数的一个非常方便的特性是函数参数可以有default values

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

如果一个参数是一个闭包,有没有办法让它有一个默认值?请看下面的例子:

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

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

ecfsfe2w

ecfsfe2w1#

是的,函数只是值,所以你可以提供它们作为默认值

// 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
)
{  }

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

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

sendBody(success: { _ in print("ah, yeah!") })

如果你正在这样做,还值得注意:如果调用者使用尾随闭包语法,这将是参数列表中的 last 闭包。所以你希望最后一个是用户最有可能想要提供的,这可能是success闭包:

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?")
}

除此之外,函数声明中的顺序对调用者来说并不重要--默认参数可以以任何顺序提供。

tv6aics1

tv6aics12#

你可以做这样的事

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) {
}

然后,您可以调用这些方法中的任何一个。注意sendBody,它是用默认参数调用的。

sendBody()
sendBody(body: , success: , failure: )

你也可以调用所有的变量,比如只传递上面方法中的一个参数,因为你必须用命名参数来调用它。

sendBody()
sendBody(body:)

sendBody(failure: )
sendBody(success:)

sendBody(body: , success: , failure: )
nx7onnlm

nx7onnlm3#

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

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

那你就能做到

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

someFunction(age: 19)

您可能需要也可能不需要使用@escaping关键字。如果您需要,Xcode会在编译时发出警告。
基本上,如果你的函数改变了外部变量,你需要使用@escaping

4nkexdtk

4nkexdtk4#

我更喜欢指定面向公共的闭包的方法-特别是你可能想存储在某个地方以供以后使用的完成闭包-是为它们定义一个typealias,如下所示:

public typealias FooCompletion = (String) -> Void

然后在面向公众的功能中,您可以轻松地将其设置为可选的,如下所示:

var onCompletion: FooCompletion? = nil

public func foo(completion: FooCompletion? = nil) {
    // Store completion for later
    onCompletion = completion
}

completion参数是可选的,所以它可以是nil,默认值是nil,这意味着调用者不必指定它。此外,由于您在多个地方使用该类型,因此如果您需要在开发期间更改其定义,则只有一个地方可以这样做。调用也很容易:

private func someBackgroundThing() {
    var completionString = "done"
    ...
    onCompletion?(completionString)
}

相关问题