Подтвердить что ты не робот

Может ли быстрое закрытие установить значение по умолчанию при использовании в качестве параметра в функции?

Довольно удобная функция функций Swift заключается в том, что параметры функции могут иметь значения по умолчанию:

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

Есть ли способ заставить разработчика не передавать значение для success или failure при вызове sendBody?

4b9b3361

Ответ 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!") })

Также стоит отметить, если вы это сделаете: если вызывающий использует синтаксис закрывающего закрытия, это будет последнее закрытие в списке аргументов. Таким образом, вы хотите, чтобы последняя была той, которую пользователь, скорее всего, захочет предоставить, что, вероятно, является завершением успеха:

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

Кроме этого, порядок в объявлении функции не имеет значения для вызывающего абонента - аргументы по умолчанию могут предоставляться в любом порядке.

Ответ 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 и Completion Handler для этого.