Wie macht man schnell einen optionalen Verschluss?

93

Ich versuche, in Swift ein Argument zu deklarieren, das optional geschlossen werden kann. Die von mir deklarierte Funktion sieht folgendermaßen aus:

class Promise {

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

}

Swift beschwert sich jedoch darüber, dass "Gebundener Wert in einer Bedingung ein optionaler Typ sein muss", in dem "if let" deklariert ist.

Marcosc
quelle
Verwenden Sie nur einen Abschluss mit Parametern.
Catanore

Antworten:

113

Sie sollten den optionalen Verschluss in Klammern setzen. Dadurch wird der ?Bediener ordnungsgemäß erfasst .

func then(onFulfilled: ()->(), onReject: (()->())?){       
    if let callableRjector = onReject {
      // do stuff! 
    }
 }
Cezar
quelle
Wissen Sie, warum Sie es in Klammern setzen müssen?
Marcosc
5
Wahrscheinlich, um Mehrdeutigkeiten zu beseitigen. Wenn der optionale Abschluss einen Rückgabewert haben sollte, könnte es verwirrend werden, was ()->Int?bedeutet.
Cezar
3
Außerdem aus dem Swift-Buch: „Wenn Sie einen optionalen Typ deklarieren, müssen Sie Klammern verwenden, um das? Operator. Um beispielsweise ein optionales Array von Ganzzahlen zu deklarieren, schreiben Sie die Typanmerkung als (Int [])?; Int [] schreiben? erzeugt einen Fehler. "
Cezar
@ Cezar Könnten Sie bitte ein wenig erklären, warum und wo "Optionaler Verschluss" verwendet werden soll? Ich bin gespannt darauf.
iLearner
@Cezar Im Moment nicht auf einem Mac, daher ist meine Syntax möglicherweise etwas falsch, aber denken Sie daran, dass dies ?wirklich nur Zucker Optional<T>ist. Sie können also auch `func then (onFulfilled: () -> (), onReject: Optional <() schreiben. -> ()>) {`dann würden Sie das Extra nicht brauchen (), obwohl IMO das ()?schöner ist. Sie können es auch mit einem Typealias wietypealias RejectHandler = () -> () func then(onFulfilled: ()->(), onReject: RejectHandler?) {
Andrew Carter
62

Um den Code noch kürzer zu machen, können wir ihn beim Aufrufen nilals Standardwert für onRejectParameter und optionale Verkettung verwenden ?():

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

Auf diese Weise können wir onRejectParameter weglassen , wenn wir thenfunction aufrufen .

then({ /* on fulfilled */ })

Wir können auch die Trailing-Closure-Syntax verwenden, um onRejectParameter an die thenFunktion zu übergeben:

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

Hier ist ein Blog-Beitrag darüber.

Evgenii
quelle
34

Da ich davon ausgehe, dass dieser "optionale" Abschluss einfach nichts bewirken sollte, können Sie einen Parameter mit einem leeren Abschluss als Standardwert verwenden:

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

Diese Funktion kann jetzt mit oder ohne onRejectRückruf aufgerufen werden

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

Swift ist Optionals?hier nicht nötig !

DiegoFrings
quelle
Das ist eine schöne Lösung!
Roland T.
6

Vielleicht ist es ein sauberer Weg. Besonders wenn der Verschluss komplizierte Parameter hat.

typealias SimpleCallBack = () -> ()

class Promise {

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

}
Seifolahi
quelle