Program Swift saya macet dengan EXC_BAD_INSTRUCTION
dan salah satu dari kesalahan serupa berikut. Apa artinya kesalahan ini, dan bagaimana cara memperbaikinya?
Kesalahan fatal: Tidak terduga ditemukan nil saat membuka bungkus nilai Opsional
atau
Kesalahan fatal: Tidak terduga ditemukan nihil sementara secara implisit membuka bungkusan nilai Opsional
Posting ini dimaksudkan untuk mengumpulkan jawaban atas masalah "yang tidak terduga ditemukan", sehingga tidak tersebar dan sulit ditemukan. Jangan ragu untuk menambahkan jawaban Anda sendiri atau mengedit jawaban wiki yang ada.
swift
exception
error-handling
pkamb
sumber
sumber
Jawaban:
Jawaban ini adalah wiki komunitas . Jika Anda merasa ini bisa dibuat lebih baik, silakan mengeditnya !
Latar Belakang: Apa itu Opsional?
Dalam Swift,
Optional
adalah tipe generik yang dapat berisi nilai (jenis apa pun), atau tidak ada nilai sama sekali.Dalam banyak bahasa pemrograman lain, nilai "sentinel" tertentu sering digunakan untuk menunjukkan kurangnya nilai . Dalam Objective-C, misalnya,
nil
( pointer nol ) menunjukkan tidak adanya objek. Tetapi ini menjadi lebih rumit ketika bekerja dengan tipe primitif - harus-1
digunakan untuk menunjukkan tidak adanya bilangan bulat, atau mungkinINT_MIN
, atau bilangan bulat lainnya? Jika nilai tertentu apa pun yang dipilih berarti "tidak ada bilangan bulat", itu berarti tidak dapat lagi diperlakukan sebagai nilai yang valid .Swift adalah bahasa jenis-aman, yang berarti bahasa tersebut membantu Anda untuk lebih jelas tentang jenis nilai yang dapat digunakan oleh kode Anda. Jika bagian dari kode Anda mengharapkan sebuah String, ketik safety mencegah Anda dari melewatkannya sebuah Int secara tidak sengaja.
Di Swift, semua jenis dapat dibuat opsional . Nilai opsional dapat mengambil nilai apa pun dari jenis aslinya, atau nilai khusus
nil
.Opsional didefinisikan dengan
?
akhiran pada tipe:Kurangnya nilai dalam opsional ditunjukkan oleh
nil
:(Perhatikan bahwa ini
nil
tidak sama dengannil
di Objective-C. Di Objective-C,nil
adalah tidak adanya penunjuk objek yang valid ; di Swift, Opsional tidak terbatas pada objek / jenis referensi. Opsional berperilaku mirip dengan Haskell's Maybe .)Mengapa saya mendapatkan " kesalahan fatal: tiba-tiba ditemukan nol saat membuka nilai opsional "?
Dalam rangka untuk mengakses nilai opsional ini (jika memiliki satu sama sekali), Anda perlu membuka bungkusan itu. Nilai opsional dapat dibuka dengan aman atau paksa. Jika Anda membuka paksa opsi, dan tidak memiliki nilai, program Anda akan macet dengan pesan di atas.
Xcode akan menunjukkan kepada Anda crash dengan menyorot sebaris kode. Masalahnya terjadi pada baris ini.
Kecelakaan ini dapat terjadi dengan dua jenis force-unwrap:
1. Kekuatan Eksplisit Tidak Membuka
Ini dilakukan dengan
!
operator pada opsional. Sebagai contoh:Seperti
anOptionalString
yangnil
di sini, Anda akan mendapatkan kecelakaan pada baris di mana Anda memaksa unwrap itu.2. Opsional Unwrapped secara implisit
Ini didefinisikan dengan
!
, bukan tipe?
setelah.Opsional ini diasumsikan mengandung nilai. Oleh karena itu, setiap kali Anda mengakses opsi yang secara terbuka tidak tersirat, itu akan secara otomatis dibuka untuk Anda. Jika tidak mengandung nilai, itu akan macet.
Untuk mengetahui variabel yang menyebabkan kerusakan, Anda dapat menahan ⌥sambil mengeklik untuk menampilkan definisi, tempat Anda dapat menemukan jenis opsional.
IBOutlet, khususnya, biasanya merupakan opsi yang secara implisit tidak terbuka. Ini karena xib atau storyboard Anda akan menautkan outlet pada saat runtime, setelah inisialisasi. Karena itu Anda harus memastikan bahwa Anda tidak mengakses outlet sebelum mereka masuk. Anda juga harus memeriksa bahwa koneksi sudah benar dalam file storyboard / xib Anda, jika tidak, nilainya akan
nil
saat runtime, dan karena itu crash ketika mereka secara implisit membuka bungkusan. . Saat memperbaiki koneksi, coba hapus baris kode yang mendefinisikan outlet Anda, lalu sambungkan kembali.Kapan saya harus memaksa membuka bungkusan Opsional?
Angkatan Tidak Dibongkar Secara Eksplisit
Sebagai aturan umum, Anda tidak boleh memaksakan secara terbuka membuka opsi dengan
!
operator. Mungkin ada kasus di mana penggunaan!
dapat diterima - tetapi Anda hanya boleh menggunakannya jika Anda yakin 100% bahwa opsional mengandung nilai.Meskipun mungkin ada kesempatan di mana Anda bisa menggunakan pembungkusan paksa, karena Anda tahu fakta bahwa opsional mengandung nilai - tidak ada satu tempat pun di mana Anda tidak bisa membuka bungkusan opsional itu dengan aman.
Opsional Unwrapped secara implisit
Variabel-variabel ini dirancang sehingga Anda dapat menunda tugas mereka sampai nanti dalam kode Anda. Adalah tanggung jawab Anda untuk memastikan mereka memiliki nilai sebelum Anda mengaksesnya. Namun, karena mereka melibatkan pembongkaran paksa, mereka secara inheren tidak aman - karena mereka menganggap nilai Anda tidak-nol, meskipun menetapkan nihil valid.
Anda seharusnya hanya menggunakan opsional yang tidak dibungkus secara implisit sebagai pilihan terakhir . Jika Anda dapat menggunakan variabel lazy , atau memberikan nilai default untuk sebuah variabel - Anda harus melakukannya daripada menggunakan opsional yang terbuka secara implisit.
Namun, ada beberapa skenario di mana opsional tersirat secara terbuka bermanfaat , dan Anda masih dapat menggunakan berbagai cara untuk membuka bungkusnya dengan aman seperti yang tercantum di bawah ini - tetapi Anda harus selalu menggunakannya dengan hati-hati.
Bagaimana saya bisa dengan aman berurusan dengan Opsional?
Cara paling sederhana untuk memeriksa apakah suatu opsional mengandung suatu nilai, adalah dengan membandingkannya
nil
.Namun, 99,9% dari waktu ketika bekerja dengan opsional, Anda sebenarnya ingin mengakses nilai yang dikandungnya, jika mengandungnya sama sekali. Untuk melakukan ini, Anda dapat menggunakan Binding Opsional .
Penjilidan Opsional
Penjilidan Opsional memungkinkan Anda untuk memeriksa apakah suatu opsi mengandung nilai - dan memungkinkan Anda untuk menetapkan nilai yang tidak terbungkus ke variabel atau konstanta baru. Ini menggunakan sintaks
if let x = anOptional {...}
atauif var x = anOptional {...}
, tergantung jika Anda perlu mengubah nilai variabel baru setelah mengikatnya.Sebagai contoh:
Yang dilakukan adalah pertama-tama memeriksa apakah opsi berisi nilai. Jika tidak , maka 'terbuka' nilai ditugaskan untuk variabel baru (
number
) - yang kemudian dapat dengan bebas menggunakan seolah-olah itu non-opsional. Jika opsional tidak mengandung nilai, maka klausa lain akan dipanggil, seperti yang Anda harapkan.Apa yang rapi tentang pengikatan opsional, adalah Anda dapat membuka beberapa opsi secara bersamaan. Anda bisa memisahkan pernyataan dengan koma. Pernyataan ini akan berhasil jika semua opsi tidak dibuka.
Trik lain yang rapi adalah Anda juga dapat menggunakan koma untuk memeriksa kondisi tertentu pada nilai, setelah membuka bungkusnya.
Satu-satunya tangkapan dengan menggunakan penjilidan opsional dalam pernyataan if, adalah bahwa Anda hanya dapat mengakses nilai yang belum dibuka dari dalam lingkup pernyataan tersebut. Jika Anda membutuhkan akses ke nilai dari luar ruang lingkup pernyataan, Anda dapat menggunakan pernyataan penjaga .
Sebuah pernyataan penjaga memungkinkan Anda untuk menentukan kondisi untuk sukses - dan ruang lingkup saat hanya akan terus mengeksekusi jika kondisi yang terpenuhi. Mereka didefinisikan dengan sintaks
guard condition else {...}
.Jadi, untuk menggunakannya dengan penjilidan opsional, Anda dapat melakukan ini:
(Perhatikan bahwa di dalam tubuh penjaga, Anda harus menggunakan salah satu pernyataan transfer kontrol untuk keluar dari lingkup kode yang saat ini mengeksekusi).
Jika
anOptionalInt
mengandung nilai, itu akan dibuka dan ditugaskan kenumber
konstanta baru . Kode setelah penjaga kemudian akan melanjutkan eksekusi. Jika tidak mengandung nilai - penjaga akan mengeksekusi kode di dalam tanda kurung, yang akan menyebabkan transfer kontrol, sehingga kode segera setelah itu tidak akan dieksekusi.Hal yang benar-benar rapi tentang pernyataan penjaga adalah nilai yang belum dibuka sekarang tersedia untuk digunakan dalam kode yang mengikuti pernyataan (seperti yang kita tahu bahwa kode di masa depan hanya dapat dieksekusi jika opsional memiliki nilai). Ini bagus untuk menghilangkan 'piramida kehancuran' yang dibuat dengan membuat pernyataan if ganda.
Sebagai contoh:
Penjaga juga mendukung trik rapi yang sama yang didukung oleh pernyataan if, seperti membuka beberapa opsi secara bersamaan dan menggunakan
where
klausa.Apakah Anda menggunakan pernyataan if atau guard sepenuhnya tergantung pada apakah kode di masa depan mengharuskan opsional untuk mengandung nilai.
Operator Penggabungan Nil
The Nil penggabungan Operator adalah versi singkat bagus dari operator kondisional terner , terutama dirancang untuk mengkonversi optionals untuk non-optionals. Ini memiliki sintaks
a ?? b
, di manaa
adalah tipe opsional dan tipeb
yang samaa
(walaupun biasanya non-opsional).Ini pada dasarnya memungkinkan Anda mengatakan "Jika
a
berisi nilai, buka bungkusannya. Jika tidak maka kembalilahb
sebagai gantinya ”. Misalnya, Anda dapat menggunakannya seperti ini:Ini akan menentukan
number
konstantaInt
tipe, yang akan mengandung nilaianOptionalInt
, jika mengandung nilai, atau0
sebaliknya.Ini hanya singkatan untuk:
Rantai opsional
Anda dapat menggunakan Chaining Opsional untuk memanggil metode atau mengakses properti pada opsional. Ini hanya dilakukan dengan suffixing nama variabel dengan
?
ketika menggunakannya.Sebagai contoh, katakanlah kita memiliki variabel
foo
, ketikFoo
instance opsional .Jika kami ingin memanggil metode
foo
yang tidak mengembalikan apa pun, kami dapat melakukannya:Jika
foo
berisi nilai, metode ini akan dipanggil. Jika tidak, tidak ada hal buruk yang akan terjadi - kode akan terus dijalankan.(Ini adalah perilaku yang mirip dengan mengirim pesan ke
nil
di Objective-C)Ini karena itu juga dapat digunakan untuk mengatur properti serta metode panggilan. Sebagai contoh:
Sekali lagi, tidak ada yang buruk akan terjadi di sini jika
foo
adalahnil
. Kode Anda akan terus dijalankan.Trik lain yang rapi yang memungkinkan Anda melakukan perangkaian opsional adalah memeriksa apakah menyetel properti atau memanggil metode berhasil. Anda dapat melakukan ini dengan membandingkan nilai kembali ke
nil
.(Ini karena nilai opsional akan kembali
Void?
daripadaVoid
pada metode yang tidak mengembalikan apa pun)Sebagai contoh:
Namun, hal-hal menjadi sedikit lebih rumit ketika mencoba mengakses properti atau memanggil metode yang mengembalikan nilai. Karena
foo
bersifat opsional, apa pun yang dikembalikan darinya juga akan opsional. Untuk mengatasinya, Anda dapat membuka bungkusan opsional yang dikembalikan menggunakan salah satu metode di atas - atau membuka bungkusannyafoo
sendiri sebelum mengakses metode atau metode panggilan yang mengembalikan nilai.Juga, seperti namanya, Anda dapat 'rantai' pernyataan ini bersama-sama. Ini berarti bahwa jika
foo
memiliki properti opsionalbaz
, yang memiliki propertiqux
- Anda dapat menulis yang berikut:Sekali lagi, karena
foo
danbaz
bersifat opsional, nilai yang dikembalikan dariqux
akan selalu menjadi opsional terlepas dari apakahqux
itu sendiri opsional.map
danflatMap
Fitur yang sering kurang digunakan dengan opsional adalah kemampuan untuk menggunakan
map
danflatMap
fungsinya. Ini memungkinkan Anda untuk menerapkan transformasi non-opsional ke variabel opsional. Jika opsional memiliki nilai, Anda dapat menerapkan transformasi yang diberikan padanya. Jika tidak memiliki nilai, itu akan tetapnil
.Misalnya, katakanlah Anda memiliki string opsional:
Dengan menerapkan
map
fungsi ke dalamnya - kita dapat menggunakanstringByAppendingString
fungsi untuk menggabungkannya ke string lain.Karena
stringByAppendingString
mengambil argumen string non-opsional, kami tidak dapat memasukkan string opsional kami secara langsung. Namun, dengan menggunakanmap
, kita dapat menggunakan izinstringByAppendingString
untuk digunakan jikaanOptionalString
memiliki nilai.Sebagai contoh:
Namun, jika
anOptionalString
tidak memiliki nilai,map
akan kembalinil
. Sebagai contoh:flatMap
bekerja serupa denganmap
, kecuali itu memungkinkan Anda untuk mengembalikan opsi lain dari dalam tubuh penutupan. Ini berarti Anda dapat memasukkan opsi ke dalam proses yang membutuhkan input non-opsional, tetapi dapat menampilkan sendiri opsi itu.try!
Sistem penanganan kesalahan Swift dapat digunakan dengan aman dengan Do-Try-Catch :
Jika
someThrowingFunc()
melempar kesalahan, kesalahan akan ditangkap dengan aman dicatch
blok.The
error
konstan Anda lihat dalamcatch
blok belum dinyatakan oleh kami - itu secara otomatis olehcatch
.Anda juga dapat mendeklarasikan
error
diri Anda sendiri, itu memiliki keuntungan karena dapat melemparkannya ke format yang bermanfaat, misalnya:Menggunakan
try
cara ini adalah cara yang tepat untuk mencoba, menangkap dan menangani kesalahan yang berasal dari fungsi melempar.Ada juga
try?
yang menyerap kesalahan:Tetapi sistem penanganan kesalahan Swift juga menyediakan cara untuk "memaksa mencoba" dengan
try!
:Konsep-konsep yang dijelaskan dalam posting ini juga berlaku di sini: jika ada kesalahan, aplikasi akan macet.
Anda hanya boleh menggunakannya
try!
jika Anda dapat membuktikan bahwa hasilnya tidak akan pernah gagal dalam konteks Anda - dan ini sangat jarang.Sebagian besar waktu Anda akan menggunakan sistem Do-Try-Catch yang lengkap - dan yang opsional
try?
,, dalam kasus yang jarang terjadi di mana penanganan kesalahan tidak penting.Sumber daya
sumber
compactMap()
alih-alihflatMap()
.TL; DR jawab
Dengan sedikit pengecualian , aturan ini berwarna emas:
Hindari penggunaan
!
Deklarasikan variabel opsional (
?
), bukan opsional yang tidak terbuka (IUO) (!
)Dengan kata lain, lebih baik gunakan:
var nameOfDaughter: String?
Dari pada:
var nameOfDaughter: String!
Buka bungkusan variabel opsional menggunakan
if let
atauguard let
Baik membuka bungkusan variabel seperti ini:
Atau seperti ini:
Jawaban ini dimaksudkan untuk ringkas, untuk pemahaman penuh membaca jawaban yang diterima
Sumber daya
sumber
Pertanyaan ini muncul SEPANJANG WAKTU di SO. Ini adalah salah satu hal pertama yang dihadapi oleh pengembang Swift baru.
Latar Belakang:
Swift menggunakan konsep "Opsional" untuk menangani nilai yang dapat mengandung nilai, atau tidak. Dalam bahasa lain seperti C, Anda dapat menyimpan nilai 0 dalam variabel untuk menunjukkan bahwa itu tidak mengandung nilai. Namun, bagaimana jika 0 adalah nilai yang valid? Maka Anda mungkin menggunakan -1. Bagaimana jika -1 adalah nilai yang valid? Dan seterusnya.
Opsional Swift memungkinkan Anda mengatur variabel jenis apa pun untuk mengandung nilai yang valid, atau tidak ada nilai.
Anda memberi tanda tanya setelah tipe ketika Anda mendeklarasikan variabel ke mean (tipe x, atau tidak ada nilai).
Opsional sebenarnya adalah sebuah wadah selain berisi variabel jenis tertentu, atau tidak sama sekali.
Pilihan harus "dibuka" untuk mengambil nilai di dalamnya.
"!" operator adalah operator "buka paksa". Itu mengatakan "percayalah padaku. Aku tahu apa yang aku lakukan. Aku menjamin bahwa ketika kode ini berjalan, variabel tidak akan mengandung nihil." Jika Anda salah, Anda mengalami crash.
Kecuali Anda benar - benar tahu apa yang Anda lakukan, hindari "!" memaksa membuka bungkusan operator. Ini mungkin sumber crash terbesar untuk memulai programmer Swift.
Cara berurusan dengan opsional:
Ada banyak cara lain untuk berurusan dengan opsional yang lebih aman. Berikut adalah beberapa (bukan daftar lengkap)
Anda dapat menggunakan "penjilidan opsional" atau "jika membiarkan" mengatakan "jika opsi ini mengandung nilai, simpan nilai itu ke variabel baru, non-opsional. Jika opsional tidak mengandung nilai, lewati badan pernyataan if ini ".
Berikut adalah contoh pengikatan opsional dengan
foo
opsional kami :Perhatikan bahwa variabel yang Anda tetapkan saat menggunakan biding opsional hanya ada (hanya "dalam cakupan") di badan pernyataan if.
Sebagai alternatif, Anda bisa menggunakan pernyataan penjaga, yang memungkinkan Anda keluar dari fungsi Anda jika variabelnya nihil:
Pernyataan penjaga ditambahkan dalam Swift 2. Guard memungkinkan Anda mempertahankan "jalur emas" melalui kode Anda, dan menghindari tingkat peningkatan bersarang yang kadang-kadang dihasilkan dari penggunaan "jika dibiarkan" pengikatan opsional.
Ada juga konstruksi yang disebut "operator penggabungan nil". Dibutuhkan bentuk "optional_var ?? replacement_val". Ini mengembalikan variabel non-opsional dengan tipe yang sama dengan data yang terkandung dalam opsional. Jika opsional berisi nil, itu mengembalikan nilai ekspresi setelah "??" simbol.
Jadi Anda bisa menggunakan kode seperti ini:
Anda juga bisa menggunakan try / catch atau guard error handling, tetapi umumnya salah satu teknik lain di atas lebih bersih.
EDIT:
Satu lagi, gotcha yang sedikit lebih halus dengan opsional adalah "opsional yang tidak terbuka secara implisit. Ketika kita mendeklarasikan foo, kita dapat mengatakan:
Dalam hal ini foo masih merupakan opsional, tetapi Anda tidak perlu membukanya untuk referensi. Itu berarti setiap kali Anda mencoba referensi foo, Anda gagal jika tidak ada.
Jadi kode ini:
Akan macet karena referensi ke properti Kapitalisasi foo meskipun kami tidak membuka paksa foo. hasil cetak terlihat bagus, tetapi tidak.
Dengan demikian, Anda ingin benar-benar berhati-hati dengan pilihan yang secara implisit tidak terbuka. (dan mungkin bahkan menghindari mereka sepenuhnya sampai Anda memiliki pemahaman yang kuat tentang opsional.)
Intinya: Ketika Anda pertama kali belajar Swift, berpura-pura "!" karakter bukan bagian dari bahasa. Mungkin membuat Anda kesulitan.
sumber
guard
klausa. Tidak ada tentang penggunaanif var
yang sama validnya dengan konstrukif let
. Tidak ada apa-apa tentangwhere
klausa yang saya rasa layak disebutkan ketika kita berbicara tentangif let
mengikat (ini menghilangkan seluruh lapisan sarang dalam banyak kasus). Tidak ada apa pun tentang rantai opsional.Karena jawaban di atas dengan jelas menjelaskan cara bermain dengan aman dengan Opsional. Saya akan mencoba menjelaskan apa yang benar-benar opsional dalam cepat.
Cara lain untuk mendeklarasikan variabel opsional adalah
var i : Optional<Int>
Dan jenis opsional hanyalah enumerasi dengan dua kasus, yaitu
Jadi untuk menetapkan nol ke variabel kami 'i'. Kita dapat melakukan
var i = Optional<Int>.none
atau untuk menetapkan suatu nilai, kita akan memberikan beberapa nilaivar i = Optional<Int>.some(28)
Menurut swift, 'nil' adalah tidak adanya nilai. Dan untuk membuat instance yang diinisialisasi dengan
nil
Kita harus menyesuaikan diri dengan protokol yang disebutExpressibleByNilLiteral
dan hebat jika Anda dapat menebaknya, hanyaOptionals
mematuhiExpressibleByNilLiteral
dan menyesuaikan dengan tipe lain tidak disarankan.ExpressibleByNilLiteral
memiliki metode tunggal yang disebutinit(nilLiteral:)
yang menginisialisasi instace dengan nil. Anda biasanya tidak akan memanggil metode ini dan menurut dokumentasi cepat, tidak disarankan untuk memanggil inisialisasi ini secara langsung ketika kompiler memanggilnya setiap kali Anda menginisialisasi tipe opsional dengannil
literal.Bahkan saya sendiri harus membungkus (tidak bermaksud kata-kata) kepalaku di sekitar Opsional: D Happy Swfting All .
sumber
Pertama, Anda harus tahu apa nilai Opsional. Anda dapat melangkah ke Bahasa Pemrograman Swift untuk detail.
Kedua, Anda harus tahu nilai opsional memiliki dua status. Satu adalah nilai penuh, dan yang lainnya adalah nilai nol. Jadi sebelum Anda menerapkan nilai opsional, Anda harus memeriksa negara mana itu.
Anda bisa menggunakan
if let ...
atauguard let ... else
dan sebagainya.Salah satu cara lain, jika Anda tidak ingin memeriksa status variabel sebelum implementasi Anda, Anda juga dapat menggunakannya
var buildingName = buildingName ?? "buildingName"
.sumber
Saya memiliki kesalahan ini satu kali ketika saya mencoba untuk menetapkan nilai Outlet saya dari metode persiapan untuk segue sebagai berikut:
Kemudian saya mengetahui bahwa saya tidak dapat menetapkan nilai outlet controller tujuan karena controller belum dimuat atau diinisialisasi.
Jadi saya memecahkannya dengan cara ini:
Pengendali Tujuan:
Saya harap jawaban ini membantu siapa pun di luar sana dengan masalah yang sama seperti saya menemukan jawaban yang ditandai adalah sumber yang bagus untuk memahami pilihan dan bagaimana mereka bekerja tetapi belum membahas masalah itu sendiri secara langsung.
sumber
updateView
pengontrol tujuan;)updateView
kontroler tujuan tidak diperlukan dalam kasus ini karena saya menggunakanname
variabel untuk mengaturnameLabel.text
diviewDidLoad
. Tetapi jika kita melakukan banyak pengaturan, itu pasti akan lebih baik membuat fungsi lain dan memanggilnyaviewDidLoad
.Pada dasarnya Anda mencoba menggunakan nilai nihil di tempat-tempat di mana Swift hanya memperbolehkan yang tidak nihil, dengan memberi tahu kompiler untuk mempercayai Anda bahwa tidak akan pernah ada nilai nihil di sana, sehingga memungkinkan aplikasi Anda untuk dikompilasi.
Ada beberapa skenario yang menyebabkan kesalahan fatal seperti ini:
membuka paksa:
Jika
someVariable
nihil, maka Anda akan mengalami kerusakan. Dengan melakukan pembungkusan paksa, Anda memindahkan tanggung jawab nil check dari compiler ke Anda, pada dasarnya dengan melakukan bongkar paksa Anda menjamin ke kompiler bahwa Anda tidak akan pernah memiliki nilai nil di sana. Dan coba tebak apa yang terjadi jika entah bagaimana nilai nol berakhir disomeVariable
?Larutan? Gunakan penjilidan opsional (alias jika-biarkan), lakukan pemrosesan variabel di sana:
gips paksa (bawah):
Di sini dengan paksa casting Anda memberitahu kompiler untuk tidak lagi khawatir, karena Anda akan selalu memiliki
Rectangle
instance di sana. Dan selama itu berlaku, Anda tidak perlu khawatir. Masalah dimulai ketika Anda atau kolega Anda dari proyek mulai mengedarkan nilai-nilai non-persegi panjang.Larutan? Gunakan penjilidan opsional (alias jika-biarkan), lakukan pemrosesan variabel di sana:
Opsinya terbuka secara implisit. Mari kita asumsikan Anda memiliki definisi kelas berikut:
Sekarang, jika tidak ada yang mengacaukan
name
properti dengan mengaturnyanil
, maka ia berfungsi seperti yang diharapkan, namun jikaUser
diinisialisasi dari JSON yang tidak memilikiname
kunci, maka Anda mendapatkan kesalahan fatal ketika mencoba menggunakan properti.Larutan? Jangan menggunakannya :) Kecuali Anda 102% yakin bahwa properti akan selalu memiliki nilai nihil pada saat itu perlu digunakan. Dalam kebanyakan kasus, mengonversi ke opsional atau non-opsional akan berfungsi. Menjadikannya non-opsional juga akan menghasilkan kompiler membantu Anda dengan memberi tahu jalur kode yang Anda lewatkan memberikan nilai ke properti itu
Outlet yang tidak terhubung, atau belum terhubung. Ini adalah kasus khusus dari skenario # 3. Pada dasarnya Anda memiliki beberapa kelas XIB yang ingin Anda gunakan.
Sekarang jika Anda melewatkan menghubungkan outlet dari editor XIB, maka aplikasi akan macet segera setelah Anda ingin menggunakan outlet. Larutan? Pastikan semua outlet terhubung. Atau gunakan
?
operator pada mereka:emailTextField?.text = "[email protected]"
. Atau menyatakan outlet sebagai opsional, meskipun dalam hal ini kompiler akan memaksa Anda untuk membuka seluruh kode.Nilai yang berasal dari Objective-C, dan yang tidak memiliki penjelasan nullability. Mari kita asumsikan kita memiliki kelas Objective-C berikut:
Sekarang jika tidak ada penjelasan nullability ditentukan (baik secara eksplisit atau melalui
NS_ASSUME_NONNULL_BEGIN
/NS_ASSUME_NONNULL_END
), makaname
properti akan diimpor di Swift sebagaiString!
(IUO - opsional yang secara implisit tidak terbuka). Segera setelah beberapa kode cepat ingin menggunakan nilainya, kode tersebut akan mogok jikaname
tidak ada.Larutan? Tambahkan anotasi nullability ke kode Objective-C Anda. Namun berhati-hatilah, kompiler Objective-C sedikit permisif ketika datang ke nullability, Anda mungkin berakhir dengan nilai nil, bahkan jika Anda secara eksplisit menandainya sebagai
nonnull
.sumber
Ini lebih dari komentar yang penting dan mengapa opsional opsional yang terbuka dapat menipu ketika datang ke
nil
nilai debugging .Pikirkan kode berikut: Ini dikompilasi tanpa kesalahan / peringatan:
Namun saat runtime ia memberikan kesalahan berikut: Kesalahan fatal: Tidak terduga ditemukan nihil saat membuka bungkusan nilai opsional
Bisakah Anda memberi tahu saya objek yang mana
nil
?Kamu tidak bisa!
Kode lengkapnya adalah:
Cerpen pendek dengan menggunakan
var address : Address!
Anda bersembunyi kemungkinan bahwa variabel dapatnil
dari pembaca lain. Dan ketika crash kamu seperti "apa sih ?!address
bukan opsional, jadi mengapa saya menabrak?!.Karena itu lebih baik menulis seperti itu:
Dapatkah Anda sekarang memberi tahu saya objek mana yang dulu
nil
?Kali ini kode telah dibuat lebih jelas bagi Anda. Anda dapat merasionalisasi dan berpikir bahwa itu mungkin
address
parameter yang dibuka paksa.Kode lengkapnya adalah:
sumber
Kesalahan
EXC_BAD_INSTRUCTION
danfatal error: unexpectedly found nil while implicitly unwrapping an Optional value
muncul paling banyak ketika Anda telah menyatakan@IBOutlet
, tetapi tidak terhubung ke storyboard .Anda juga harus belajar tentang cara kerja Opsional , yang disebutkan dalam jawaban lain, tetapi ini adalah satu-satunya waktu yang paling banyak muncul bagi saya.
sumber
@IBOutlet
penyebab kesalahan ini memiliki kesalahan Fatal: Tidak terduga ditemukan nihil sementara secara implisit membuka bungkusan versi nilai opsional kesalahan?Jika Anda mendapatkan kesalahan ini di CollectionView coba buat file CustomCell dan Custom xib juga.
tambahkan kode ini di ViewDidLoad () di mainVC.
sumber
Saya menemukan kesalahan ini saat membuat segue dari pengontrol tampilan tabel ke pengontrol tampilan karena saya lupa menentukan nama kelas khusus untuk pengontrol tampilan di storyboard utama.
Sesuatu yang sederhana yang perlu diperiksa jika semuanya terlihat ok
sumber