Önemli hata: sınıf için uygulanmamış başlatıcı 'init (coder :)' kullanımı


157

Geri kalan projeme Swift ile devam etmeye karar verdim. Özel sınıfı (alt sınıfı UIViewcontroller) film şeridi görünüm denetleyicime eklediğimde ve projeyi yüklediğimde, uygulama aniden aşağıdaki hatayla kilitleniyor:

ölümcül hata: sınıf için uygulanmamış başlatıcı 'init (coder :)' kullanımı

Bu bir kod:

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.
    }
    */
}

Lütfen bir şey önerin

Yanıtlar:


208

Konu

Bunun nedeni init?(coder aDecoder: NSCoder), hedefleyicide başlatıcı bulunmamasıdır UIViewController. Bu yöntem gereklidir çünkü UIViewControllerbir UIStoryboardçağrıyı a çağırmak onu çağırır.

Biz başlatmak nasıl çalıştığını görmek için UIViewControllerbir gelen UIStoryboard, bir göz atın lütfen buraya

Objective-C ile neden bir sorun değil?

Çünkü Objective-C gerekli tüm UIViewControllerbaşlatıcıları otomatik olarak devralır .

Swift neden başlatıcıları otomatik olarak devralmıyor?

Swift , güvenlik nedeniyle varsayılan olarak başlatıcıları devralmaz. Ancak, tüm özelliklerin bir değeri (veya isteğe bağlı) olması ve alt sınıfın belirlenmiş herhangi bir başlatıcı tanımlamaması durumunda, tüm başlatıcıları üst sınıftan devralır.


Çözüm

1. İlk yöntem

init?(coder aDecoder: NSCoder)Hedefe manuel olarak uygulamaUIViewController

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

2. İkinci yöntem

Dave Wood'un aşağıdaki cevabına işaret ettiği gibi init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?), hedefinizi kaldırmak UIViewController, gerekli tüm başlangıç ​​değerlerini üst sınıftan devralacaktır.



4
Bunun için teşekkürler. Hızlı takip ... TableViewController dosyasını oluşturduğunuzda, Xcode zaten içerir init(style: UITableViewStyle) { super.init(style: style) // Custom initialization } Neden iki init fonksiyonuna sahip olabiliriz ? Ve Apple'ın varsayılan olarak 2. init'i neden içermediğine dair bir fikir var mı?
Trevor McKendrick

Bunun iOS 7 veya iOS 8 ile ilgisi yok. Bu, Swift'in başlatıcıları devralma şekliyle bağlantılı!
Sulthan

public init (görünüm: UIViewController, çerçeve: CGRect) {self.viewController = view self.imageName = "" self.actionName = "" super.init (çerçeve: çerçeve)}
scrainie

İlk yöntem işe yaradı! Dinamik tablom sonunda dinamik hücrelerle doldu !!! Çünkü hat fatalError( "init(coder:) has not been implemented")uygulamamı durdurdu.
Jose Manuel Abarca Rodríguez

26

@ 3r1d's dışında başka bir seçenek de aşağıdaki init yöntemini sınıfınızdan kaldırmaktır:

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

Bu init yöntemi de dahil olmak üzere alt sınıfın init(coder aDecoder: NSCoder!), kendi süper sınıfından miras almasını engeller . Onu dahil etmediğinizde, sınıfınız her ikisini de miras alacaktır.

Not: Daha fazla bilgi için 33:50 işaretindeki WWDC 2014 Oturum 403 "Orta Swift" e bakınız.


Oturum 403'teki açıklamaya dikkat çektiğiniz için teşekkür ederiz. Ancak çocuk sınıfında sadece kolaylık başlatıcıları varsa, süper sınıf başlatıcıları miras alacaktır değil mi?
jamiltz

1
Evet. Süper sınıf init yöntemlerinin miras alınmasını yalnızca kendi belirlenmiş init yöntemlerinizi (süper inits olarak adlandırılan) sağlarsanız önlersiniz. Daha sonra sınıfınıza ekleyerek ve sadece süper sürümü çağırarak hangi süper girişlerin destekleneceğini belirtmeniz gerekir (@ 3r1d'nin cevabında olduğu gibi)
Dave Wood

Alt sınıfınızda yalnızca (belirlenmiş) init () olmadan init () kullanılması derleme hatasına neden olur. Çünkü kolaylık init () işlevi, işlev tanımının içinde self.init () öğesini çağırmalıdır.
Ohmy

@narumolPug Bu yanlış. Belirlenmiş inityöntemleri eklemenize gerek yoktur . Çocuk sınıfınız onları süper sınıftan miras alacaktır. self.init()Süper sürümü çalıştıracak olanı arayabilirsiniz .
Dave Wood

Videonun tam anını burada bulabilirsiniz youtu.be/W1s9ZjDkSN0?t=2030
Bal

10

Swift ile aynı sorunu UICollectionViewCellsyaşayanlar için, @ 3r1d'nin önerdiği kodu UICollectionViewCellGörünüm Denetleyicisine değil , özel sınıfınıza ekleyin :

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

hangi UICollectionViewCell'den bahsediyorsunuz? Kodlayıcı ile init görünümü başlatmak için bir yoldurController
E-Riddie

Bu örnekte değil ama herkes onunla bir sorun varsa (ben yaptım) ... bir UICollectionViewController kullanmaya çalışırsanız, özel hücre .swift dosyasında kodlayıcı ile init koymak gerekir.
Nick Yap

2
Bu örnekleme yöntemini her kullandığınızda bu kodu eklemeniz gerekir stackoverflow.com/questions/24035984/…
E-Riddie

3

Swift'te koda ihtiyaç duyanlar için:

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

[Düzenle] Bu Swift'in eski bir sürümü içindi. Muhtemelen artık çalışmıyor.


3

Programlı bir collectionView hücresinde bu sorunu vardı ve op bir vc hakkında sorsa bile ben hala bir cevap ararken bu soruya indi. Benim için sorun şuydu

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

Böylece en iyi cevap işe yaramadı. Hücrede yoktu ne başlatıcı oldu:

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

Ekledikten sonra hata gitti


1

İç mekanizmanın iyi çalışmasını sağlamak için bazı yöntemler eklemek yerine, özniteliklerimi @ lazy olarak tanımlamak ve bunları doğrudan sınıf kapsamında başlatmak.


mülkünüzü isteğe bağlı olarak ile de beyan edebilirsiniz ?.
Julian
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.