【问题标题】:Can swift closures be set to a default value when used as a parameter in a function?在函数中用作参数时,可以将 swift 闭包设置为默认值吗?
【发布时间】:2015-07-01 10:42:31
【问题描述】:

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 的值?

【问题讨论】:

标签: ios macos swift


【解决方案1】:

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

// 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 闭包。所以你希望最后一个是用户最有可能想要提供的那个,这可能是成功的闭包:

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

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

【讨论】:

  • 有没有办法只将成功参数传递给函数或只传递失败参数?
  • 当然,sendBody(success: doHappyThing)sendBody(failure: { processDataSadly($0) })
  • 括号中的 是什么意思:"func doNothing(t: T) -> Void { }" 我从未在函数定义 b4 中看到过。
【解决方案2】:

你可以这样做,

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: )

【讨论】:

    【解决方案3】:

    我指定面向公众的闭包的首选方式——特别是您可能希望稍后存储在某处的完成闭包——是为它们定义一个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)
    }
    

    【讨论】:

      【解决方案4】:

      如何为函数参数设置默认值。 Swift 4 和(可能)5。

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

      那么你就可以这样做了

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

      您可能需要也可能不需要使用@escaping 关键字。请参阅Swift @escaping and Completion Handler

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-05-19
        • 1970-01-01
        • 2018-01-21
        • 1970-01-01
        • 2022-11-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多