Como fazer um fechamento opcional com rapidez?

93

Estou tentando declarar um argumento em Swift que leva um encerramento opcional. A função que declarei tem a seguinte aparência:

class Promise {

 func then(onFulfilled: ()->(), onReject: ()->()?){       
    if let callableRjector = onReject {
      // do stuff! 
    }
 }

}

Mas Swift reclama que "O valor vinculado em uma condicional deve ser um tipo opcional" onde o "if let" é declarado.

Marcosc
fonte
Considere usar apenas um encerramento com parâmetros.
catanore

Respostas:

113

Você deve colocar o fechamento opcional entre parênteses. Isso irá definir o escopo adequado do ?operador.

func then(onFulfilled: ()->(), onReject: (()->())?){       
    if let callableRjector = onReject {
      // do stuff! 
    }
 }
Cezar
fonte
Você sabe qual é o motivo de ter que colocá-lo entre parênteses?
Marcosc
5
Provavelmente para remover a ambigüidade. Se o fechamento opcional tivesse um valor de retorno, poderia ficar confuso quanto ao que ()->Int?significa.
Cezar
3
Além disso, do livro Swift: “Ao declarar um tipo opcional, certifique-se de usar parênteses para definir o escopo adequado do? operador. Como exemplo, para declarar um array opcional de inteiros, escreva a anotação de tipo como (Int []) ?; escrevendo Int []? produz um erro. ”
Cezar
@Cezar Você poderia explicar um pouco por que e onde usar "Fechamento opcional", estou curioso para saber disso.
iLearner de
@Cezar Não em um mac no momento, então minha sintaxe pode estar um pouco errada, mas lembre-se de que ?é apenas um açúcar para Optional<T>, então você também pode escrever `func then (onFulfilled: () -> (), onReject: Opcional <() -> ()>) {`então você não precisaria do extra (), embora o IMO ()?seja mais bonito. Além disso, você pode torná-lo ainda mais bonito com um typealias como typealias RejectHandler = () -> () func then(onFulfilled: ()->(), onReject: RejectHandler?) {
Andrew Carter
62

Para tornar o código ainda mais curto, podemos usar nilcomo valor padrão para o onRejectparâmetro e encadeamento opcional ?()ao chamá-lo:

func then(onFulfilled: ()->(), onReject: (()->())? = nil) {
  onReject?()
}

Desta forma, podemos omitir o onRejectparâmetro quando chamamos a thenfunção.

then({ /* on fulfilled */ })

Também podemos usar a sintaxe de encerramento final para passar o onRejectparâmetro para a thenfunção:

then({ /* on fulfilled */ }) {
  // ... on reject
}

Aqui está uma postagem no blog sobre isso.

Evgenii
fonte
34

Como eu suponho que esse fechamento "opcional" simplesmente não faça nada, você poderia usar um parâmetro com um fechamento vazio como valor padrão:

func then(onFulfilled: ()->(), onReject: ()->() = {}){       
    // now you can call your closures
    onFulfilled()
    onReject()
}

esta função agora pode ser chamada com ou sem o onRejectretorno de chamada

then({ ... })
then({ ... }, onReject: { ... })

Não há necessidade de Swift é incrível Optionals?aqui!

DiegoFrings
fonte
Esta é uma boa solução!
Roland T.
6

Talvez seja uma maneira mais limpa. Principalmente quando o fechamento possui parâmetros complicados.

typealias SimpleCallBack = () -> ()

class Promise {

func then(onFulfilled: SimpleCallBack, onReject: SimpleCallBack?){       
    if let callableRjector = onReject {
        // do stuff! 
    }
}

}
Seifolahi
fonte