简体   繁体   English

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

[英]Can swift closures be set to a default value when used as a parameter in a function?

A pretty handy feature of Swift functions is that function parameters can have default values : Swift 函数的一个非常方便的特性是函数参数可以有默认值

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

If a parameter is a closure, is there a way to make it have a default value?如果一个参数是一个闭包,有没有办法让它有一个默认值? See the example below:请参阅下面的示例:

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

Is there a way to not force the developer to pass a value for success or failure when calling sendBody ?有没有办法在调用sendBody时不强制开发人员传递successfailure的值?

Yes, functions are just values, so you can supply them as defaults是的,函数只是值,因此您可以将它们作为默认值提供

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

Alternatively, you could make them optional, that way you can detect if the caller passed one:或者,您可以将它们设为可选,这样您就可以检测调用者是否通过了一个:

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

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

Also worth noting if you're doing this: if the caller uses the trailing closure syntax, this will be the last closure in the argument list.同样值得注意的是,如果你这样做:如果调用者使用尾随闭包语法,这将是参数列表中的最后一个闭包。 So you want the last one to be the one the user is most likely to want to supply, which is probably the success closure:所以你希望最后一个是用户最有可能想要提供的,这可能是成功闭包:

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

Other than this, the order in the function declaration doesn't matter to the caller – defaulted arguments can be supplied in any order.除此之外,函数声明中的顺序与调用者无关——可以按任何顺序提供默认参数。

You could do something like this,你可以做这样的事情,

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

Then, you may be able to call either one of these methods.然后,您可以调用这些方法之一。 Notice sendBody which is called with default parameters.请注意使用默认参数调用的 sendBody。

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

You can also call with all the variants like passing just one of the argument in the above method, for that you have to call it with named parameter.您还可以使用所有变体进行调用,例如在上述方法中仅传递一个参数,为此您必须使用命名参数调用它。

sendBody()
sendBody(body:)

sendBody(failure: )
sendBody(success:)

sendBody(body: , success: , failure: )

My preferred way to specify public facing closures - in particular completion closures which you might want to store somewhere for later - is to define a typealias for them, like this:我首选的指定面向公众的闭包的方法——特别是你可能想要存储在某处以备日后使用的完成闭包——是为它们定义一个类型typealias ,如下所示:

public typealias FooCompletion = (String) -> Void

Then in the public facing function you can easily make it optional like this:然后在面向公众的功能中,您可以轻松地将其设为可选,如下所示:

var onCompletion: FooCompletion? = nil

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

The completion parameter is optional, so it's allowed to be nil , and the default value is nil , meaning the caller doesn't have to specify it. completion参数是可选的,因此允许为nil ,默认值为nil ,这意味着调用者不必指定它。 Also, because you use the type in more than one place, if you need to change its definition during development there's only one place to do so.此外,因为您在多个地方使用该类型,如果您需要在开发过程中更改其定义,则只有一个地方可以这样做。 It's easy to call too:调用也很容易:

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

How to set a default value for a function parameter.如何为函数参数设置默认值。 Swift 4 and (probably) 5. Swift 4 和(可能)5。

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

  //
  doSomething()
}

Then you can do this然后你可以这样做

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

someFunction(age: 19)

You may or may not need to use the @escaping keyword.您可能需要也可能不需要使用@escaping关键字。 See Swift @escaping and Completion Handler for that.请参阅Swift @escaping 和 Completion Handler

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM