Bagaimana Swift IF LET dievaluasi?

90

Saya telah melihat kode ini di situs Swift dan berbagai posting di sini dan saya mencoba memahami dasar-dasarnya. Bagaimana baris ini dievaluasi?

if let name = optionalName {

Saya bingung karena itu bukan nama == nama opsional, ini menetapkan nilainya, jadi bagaimana laporan itu benar dan mengapa tidak benar ketika Anda mengganti dengan john appleseed dengan nil, karena masih akan sama?

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
}
DeadZero
sumber
10
Cari "penjilidan opsional" dalam dokumentasi Swift ...
Martin R
3
Penjelasan rinci tentang opsional di dev.iachieved.it/iachievedit/?p=314 , if letsintaks ini dikenal sebagai pengikatan opsional.
Joe

Jawaban:

105

Pada dasarnya baris tersebut mengatakan, "jika Anda dapat membiarkan variabel baru namesama dengan versi non-opsional optionalName, lakukan hal berikut dengannya". Seperti yang ditunjukkan Martin, ini disebut Penjilidan Opsional .

Satu-satunya tujuan dari itu adalah untuk menguji apakah variabel opsional berisi nilai aktual dan mengikat bentuk non-opsional ke variabel sementara. Ini adalah cara yang aman untuk "membuka" sebuah opsional atau dengan kata lain, mengakses nilai yang terdapat dalam opsional. Ini sama sekali tidak menguji kesetaraan dalam bentuk apa pun. Ini hanya menguji keberadaan nilai dalam opsional.

menggambar
sumber
2
Saya akan membacanya ketika saya turun ke sana, saya baru saja memulai pengantar cepat dan itu tidak menjelaskannya. penjelasan Anda masuk akal, Terima kasih.
DeadZero
1
Mengapa kita tidak menggunakan "! =" Daripada "if let" untuk memeriksa apakah variabel opsional memiliki nilai seperti - if optionalName! = Nil {salam = "Hello, (name)"}
Nuibb
4
@Nuibb karena saat menggunakan if letkami mengikat nilai ke variabel non-opsional ( namedalam contoh ini). Contoh Anda tidak akan dikompilasi karena sekarang tidak ada variabel yang dipanggil name. Jika Anda mengubah contoh Anda untuk menggunakannya optionalNameakan dicetak sebagai Hello, Optional("John Appleseed"). Anda dapat menggunakan paksa membuka bungkus setelah memeriksa nil Hello, \(optionalName!)tetapi ini hanya lebih rentan kesalahan jika Anda memindahkan bagian kode itu ke suatu tempat tanpa centang.
menggambar
30

Opsional adalah set atau not-set (bukan nil atau nil) ... meninggalkan kita dengan keputusan penting. "Bagaimana kita harus menulis kode kita sehingga dapat bekerja dengan benar untuk 2 negara bagian?". Cara kita membuka bungkus opsional adalah yang memutuskannya untuk kita.

Ada beberapa pendekatan yang dapat Anda gunakan untuk melawan not-set opsional.

  • Jatuh!
  • Bawalah nilainya menjadi sesuatu - jika tidak ditetapkan.
  • Gagal dengan anggun yaitu tidak melakukan apa-apa, tetapi juga jika nilainya telah ditetapkan, lalu tetapkan.
  • Gagal dengan anggun yaitu tidak melakukan apa-apa jika nilainya telah ditetapkan ... lakukan sesuatu (ini hanya lebih dari satu tugas).

Di bawah ini adalah 4 pendekatan


Menggunakan pembukaan paksa akan macet jika Anda tidak memiliki nilai. Anda ingin melakukan ini jika memiliki nilai itu sangat penting, misalnya judul film (setiap film HARUS memiliki nama). !digunakan untuk membuka bungkus paksa.

movieTitle = movie.title!

Menggunakan penggabungan nil adalah cara lain yang akan memberi Anda lebih banyak kontrol , yang berarti tidak akan macet jika nilainya tidak disetel, juga tidak akan 'tidak disetel apa-apa' jika tidak disetel ... itu akan melakukan apa yang Anda perintahkan. untuk melakukan misalnya akan default / mengatur nama film ke untitled_movie jika tidak ada nama yang ditetapkan. ??digunakan untuk penggabungan nol.

var movieTitle = movie.title ?? "untitled_Movie"

Menggunakan Rangkaian opsional tidak akan melakukan apa pun jika Anda tidak memiliki nilai, dan akan menyetel nilai jika Anda memiliki nilai. Anda melakukan ini untuk sesuatu yang nilainya tidak begitu penting, misalnya untuk nama agen aktor Anda . ?digunakan untuk rangkaian opsional.

let agent = movie.leadActor?.agent //would not crash if you don't have a lead actor (optional chaining)
let agent = movie.leadActor!.agent //would crash if you don't have a lead Actor (forced wrapping)  

Menggunakan if-let(atau guardyang merupakan dua jenis pengikatan opsional ) akan memberi Anda lebih banyak kontrol , tidak akan mogok jika nilainya tidak disetel. Jika nilainya ditetapkan, maka Anda dapat melakukan sesuatu. Jika tidak disetel, Anda dapat menambahkanelse pernyataan.

if let supportingActor = movie.supportingActor{
print(" The supporting actor is \(supportingActor)}

Ini adalah cara membuka bungkus yang paling umum digunakan, karena membuka bungkus secara paksa agak tidak disarankan. Untuk diskusi lebih lanjut tentang mengapa hal itu tidak disarankan, lihat di sini . Untuk perbandingan yang bagus antara guarddan if-letlihatguard vs. if-let


Catatan samping:

Penjilidan opsional dan rantai opsional biasanya digunakan bersama:

if let agent = movie.leadActor?.agent {
ContactInfo = agent.phoneNumber
} // if-let is the optional *binding* part, the movie dot leadActor dot is the optional *chaining*
 
Madu
sumber
Mengapa membuka bungkusan paksa tidak disarankan mengingat situasi di mana movieTitle tidak pernah bisa apa pun selain string, dan semua string valid untuk movieTitle? (dan saya tidak ingin "film tanpa judul" Saya ingin "") Membuka bungkusan paksa adalah satu-satunya cara yang tepat untuk situasi ini, alangkah baiknya jika Anda dapat menghapus bagian yang mengatakan "membuka bungkusan paksa agak tidak disarankan" karena itu adalah info yang salah .
Andy
Misalkan Anda membuat panggilan jaringan dan beberapa pengembang tim server membuat keputusan yang buruk dan lupa mengirim judul film. Apakah Anda ingin aplikasi Anda mogok dalam produksi? Atau hanya menulis judul yang tidak diketahui? Faktanya beberapa film di IMDb tidak memiliki judul :). Selain itu, buka paksa menyiratkan bahwa Anda belum melakukan pencatatan atau pernyataan apa pun. Itu buruk. Karena Anda tidak akan tahu apa akar masalahnya.
Madu
Itu argumen manusia jerami, saya tidak pernah mengatakan "selalu gunakan pembukaan paksa." Hanya karena Anda tidak boleh menggunakan pembukaan paksa dalam contoh Anda, tidak berarti pembukaan paksa tidak disarankan di setiap contoh. Saya memberi Anda skenario di mana membuka bungkus paksa adalah satu-satunya solusi yang tepat dari empat yang Anda berikan. Bisakah Anda memberikan solusi yang lebih baik untuk skenario yang dinyatakan komentar saya sebelumnya? Jika tidak, harap pertimbangkan untuk mengubah komentar Anda tentang "membuka bungkusan paksa agak tidak disarankan" karena tidak disarankan tanpa mempertimbangkan konteksnya.
Andy
Jika Anda default sesuatu menjadi "" maka itu bukan lagi pilihan
Honey
Misalnya, nilai "" itu berasal dari properti teks dari instance UILabel yang dibuat di storyboard, itu opsional karena bisa menjadi nol jika Anda membuatnya secara dinamis, tetapi di sini Anda tidak membuatnya secara dinamis sehingga akan selalu berisi nilai string . Apakah Anda tidak akan menggunakan pembongkaran paksa dalam kasus ini, sebaliknya, Anda akan membukanya dengan if-let dan memberikan nilai yang identik dengan nilai defaultnya ""? Bisa, tapi itu tidak berguna, tidak perlu, dan bertele-tele. Dan bagaimana jika Anda menggunakan pustaka HTTP yang akan selalu mengembalikan kamus meskipun ada kesalahan. Itu tergantung konteks.
Andy
4

Sintaks if menerima 2 kondisi berbeda. Yang kedua, pengikatan opsional, bukanlah boolean. Ini membingungkan, karena Anda dapat menulis:

if let name = optionalName {

tapi tidak

if (let name = optionalName) {

Dokumentasi Apple (referensi Swift):

Nilai kondisi harus bertipe Boolatau tipe yang dihubungkan Bool. Kondisi tersebut juga dapat berupa deklarasi pengikatan opsional, seperti yang dibahas dalam Pengikatan Opsional .

Pierre Marty
sumber
3

if hanya mengambil ekspresi boolean, selain itu akan menimbulkan kesalahan, jadi cuplikan kode ini mengatakan

if let name = optionalName {

}else{

}

jika optionalName nihil maka kondisinya salah dan pernyataan lain akan dieksekusi. Namun jika optionalName memiliki beberapa nilai maka nilai opsional tersebut tidak terbungkus / ditetapkan ke dalam variabel konstan yaitu nama.

Anurag Bhakuni
sumber
1

Setiap kali Anda bekerja dengan referensi yang lemah, tipe opsional akan lebih baik digunakan jika membiarkan kode Anda dilindungi dengan aman dan menghindari crash Berikut adalah contohnya

var middleName :String? = "some thing"
if let isExistsMiddleName = middleName {
// do some thing here
} else {
// no middle name
}
Narendra G
sumber