Может ли быстрое закрытие установить значение по умолчанию при использовании в качестве параметра в функции?
Довольно удобная функция функций 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
?
Ответы
Ответ 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 для этого.