Kesalahan fatal: penggunaan inisialisasi initializer yang tidak diimplementasikan (coder :) 'untuk kelas

157

Saya memutuskan untuk melanjutkan proyek saya yang tersisa dengan Swift. Ketika saya menambahkan kelas khusus (subclass of UIViewcontroller) ke controller tampilan storyboard saya dan memuat proyek, aplikasi tiba-tiba crash dengan kesalahan berikut:

kesalahan fatal: penggunaan inisialisasi initializer 'init (coder :)' yang tidak diterapkan untuk kelas

Ini adalah kode:

import UIKit

class TestViewController: UIViewController {

    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        // Custom initialization
    }

    override func viewDidLoad() {
        super.viewDidLoad()
              // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    /*
    // #pragma mark - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */
}

Tolong sarankan sesuatu

Pratik Bhiyani
sumber

Jawaban:

208

Isu

Ini disebabkan oleh tidak adanya initializer init?(coder aDecoder: NSCoder)pada target UIViewController. Metode itu diperlukan karena instantiating UIViewControllerdari UIStoryboardpanggilan itu.

Untuk melihat bagaimana kami memulai UIViewControllerdari UIStoryboard, silakan lihat di sini

Mengapa ini bukan masalah dengan Objective-C?

Karena Objective-C secara otomatis mewarisi semua UIViewControllerinisialisasi yang diperlukan .

Mengapa Swift tidak secara otomatis mewarisi inisialisasi?

Swift secara default tidak mewarisi inisialisasi karena keselamatan. Tapi itu akan mewarisi semua inisialisasi dari superclass jika semua properti memiliki nilai (atau opsional) dan subkelas belum mendefinisikan inisialisasi yang ditunjuk.


Larutan

1. Metode pertama

Menerapkan init?(coder aDecoder: NSCoder)target secara manualUIViewController

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

2. Metode kedua

Menghapus init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)target Anda UIViewControllerakan mewarisi semua inisialisasi yang diperlukan dari superclass sebagai Dave Wood menunjuk pada jawabannya di bawah ini


E-Riddie
sumber
4
Terima kasih untuk ini. Tindak lanjut cepat ... Saat Anda membuat file TableViewController, Xcode sudah menyertakan init(style: UITableViewStyle) { super.init(style: style) // Custom initialization } Mengapa kita bisa memiliki dua fungsi init? Dan tahu mengapa Apple tidak memasukkan init ke-2 secara default?
Trevor McKendrick
Ini tidak ada hubungannya dengan iOS 7 atau iOS 8. Ini terhubung dengan cara Swift mewarisi inisialisasi!
Sulthan
init publik (tampilan: UIViewController, bingkai: CGRect) {self.viewController = lihat self.imageName = "" self.actionName = "" super.init (bingkai: bingkai)}
scrainie
Metode pertama berhasil! Tabel dinamis saya akhirnya diisi dengan sel dinamis !!! Semua karena saluran fatalError( "init(coder:) has not been implemented")menghentikan aplikasi saya.
Jose Manuel Abarca Rodríguez
26

Opsi lain selain @ 3r1d adalah untuk menghapus metode init berikut dari kelas Anda:

init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    // Custom initialization
}

Termasuk metode init, mencegah sub class mewarisi init(coder aDecoder: NSCoder!)dari super class-nya. Dengan tidak memasukkannya, kelas Anda akan mewarisi keduanya.

Catatan: Lihat WWDC 2014 Sesi 403 "Intermediate Swift" di sekitar tanda 33:50 untuk detail lebih lanjut.

Dave Wood
sumber
Terima kasih telah menunjukkan penjelasan pada Sesi 403. Tetapi jika kelas anak hanya memiliki inisialisasi kenyamanan maka itu akan mewarisi inisialisasi kelas super kan?
jamiltz
1
Iya. Anda hanya mencegah metode init kelas super agar tidak diwarisi jika Anda memberikan metode init yang Anda tetapkan sendiri (metode yang memanggil init super). Maka Anda harus menentukan init super mana yang didukung dengan menambahkannya ke kelas Anda dan cukup memanggil versi super (seperti dalam jawaban @ 3r1d)
Dave Wood
Hanya memiliki init () tanpa (ditunjuk) init () di kelas anak Anda akan menyebabkan kesalahan kompilasi. Itu karena kenyamanan fungsi init () harus memanggil self.init () di dalam definisi fungsi.
Ohmy
@narumolPug Itu tidak benar. Anda tidak perlu memasukkan initmetode yang ditunjuk . Kelas anak Anda akan mewarisinya dari kelas super. Anda masih dapat menelepon self.init()yang akan menjalankan versi super.
Dave Wood
Saat yang tepat dari video dapat ditemukan di sini youtu.be/W1s9ZjDkSN0?t=2030
Honey
10

Untuk orang-orang yang memiliki masalah yang sama dengan swift UICollectionViewCells, tambahkan kode yang disarankan @ 3r1d ke UICollectionViewCellkelas khusus Anda dan bukan ke View Controller:

init(coder aDecoder: NSCoder!)
{
    super.init(coder: aDecoder)
}
Nick Yap
sumber
UICollectionViewCell mana yang Anda maksud? Init dengan coder adalah cara untuk init pada viewController
E-Riddie
Tidak dalam contoh ini tetapi jika ada orang yang memiliki masalah dengan itu (saya lakukan) ... jika Anda mencoba menggunakan UICollectionViewController, dalam file .swift sel kustom Anda, Anda perlu memasukkan init dengan coder.
Nick Yap
2
Anda perlu menambahkan kode ini setiap kali Anda menggunakan cara instantiation ini stackoverflow.com/questions/24035984/…
E-Riddie
3

Bagi yang membutuhkan kode di Swift:

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

[Sunting] Ini untuk versi Swift yang lebih lama. Mungkin tidak berfungsi lagi.

MXV
sumber
3

Saya punya masalah ini dalam sel koleksiView terprogram dan meskipun op bertanya tentang vc saya masih mendarat pada pertanyaan ini ketika mencari jawaban. Bagi saya masalahnya adalah saya memang punya

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

diimplementasikan sehingga jawaban teratas tidak bekerja. Apa yang tidak saya miliki di dalam sel adalah inisialisasi:

// my programmatic cell was missing this
override init(frame: CGRect) {
    super.init(frame: frame)
}

Setelah saya menambahkannya kesalahan itu hilang

Lance Samaria
sumber
1

Daripada menambahkan beberapa metode untuk membuat mekanisme internal berfungsi dengan baik, saya akan pergi dengan mendefinisikan atribut saya sebagai @ lazy dan menginisialisasi mereka tepat di ruang lingkup kelas.

hasancan85
sumber
Anda juga dapat mendeklarasikan properti Anda sebagai opsional melalui ?.
Julian B.