Bagaimana seseorang membuat penutupan opsional dengan cepat?

93

Saya mencoba menyatakan argumen di Swift yang membutuhkan penutupan opsional. Fungsi yang telah saya nyatakan terlihat seperti ini:

class Promise {

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

}

Namun Swift mengeluh bahwa "Nilai terikat dalam kondisional harus berupa tipe Opsional" di mana "jika biarkan" dideklarasikan.

Marcosc
sumber
Pertimbangkan untuk menggunakan hanya satu penutupan dengan parameter.
catanore

Jawaban:

113

Anda harus memasukkan penutup opsional dalam tanda kurung. Ini akan mencakup ?operator dengan benar.

func then(onFulfilled: ()->(), onReject: (()->())?){       
    if let callableRjector = onReject {
      // do stuff! 
    }
 }
Cezar
sumber
Tahukah Anda apa alasan mengapa harus menyertakannya dalam tanda kurung?
Marcosc
5
Mungkin untuk menghilangkan ambiguitas. Jika penutupan opsional memiliki nilai kembali, itu bisa membingungkan untuk apa ()->Int?artinya.
Cezar
3
Selain itu, dari buku Swift: “Saat mendeklarasikan tipe opsional, pastikan untuk menggunakan tanda kurung untuk mencakup? operator. Sebagai contoh, untuk mendeklarasikan larik bilangan bulat opsional, tulis anotasi tipe sebagai (Int []) ?; menulis Int []? menghasilkan kesalahan. "
Cezar
@Cezar Bisakah Anda menjelaskan sedikit mengapa dan di mana menggunakan "Penutupan opsional", saya penasaran untuk mengetahui ini.
iLearner
@Cezar Tidak ada di mac saat ini jadi sintaks saya mungkin sedikit mati, tapi ingat ?ini sebenarnya hanya gula untuk Optional<T>, jadi Anda juga bisa menulis `func then (onFulfilled: () -> (), onReject: Opsional <() -> ()>) {`maka Anda tidak akan membutuhkan ekstra (), meskipun IMO ()?lebih cantik. Anda juga dapat membuatnya lebih cantik dengan typealias seperti typealias RejectHandler = () -> () func then(onFulfilled: ()->(), onReject: RejectHandler?) {
Andrew Carter
62

Untuk membuat kode lebih pendek, kita dapat menggunakan nilnilai default untuk onRejectparameter dan rangkaian opsional ?()saat memanggilnya:

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

Dengan cara ini kita bisa menghilangkan onRejectparameter saat kita memanggil thenfungsi.

then({ /* on fulfilled */ })

Kita juga bisa menggunakan sintaks penutupan jejak untuk melewatkan onRejectparameter ke dalam thenfungsi:

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

Berikut adalah posting blog tentang itu.

Evgenii
sumber
34

Karena saya berasumsi, bahwa penutupan "opsional" ini seharusnya tidak melakukan apa-apa, Anda dapat menggunakan parameter dengan penutupan kosong sebagai nilai default:

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

fungsi ini sekarang dapat dipanggil dengan atau tanpa onRejectcallback

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

Tidak perlu Swift keren di Optionals?sini!

DiegoFrings
sumber
Ini solusi yang bagus!
Roland T.
6

Mungkin ini cara yang lebih bersih. Khususnya jika closure memiliki parameter yang rumit.

typealias SimpleCallBack = () -> ()

class Promise {

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

}
Seifolahi
sumber