Неустранимая ошибка: использование не реализованного инициализатора 'init (coder :)' для класса


157

Я решил продолжить свой оставшийся проект со Swift. Когда я добавляю пользовательский класс (подкласс UIViewcontroller) в контроллер представления раскадровки и загружаю проект, приложение внезапно завершает работу со следующей ошибкой:

фатальная ошибка: использование не реализованного инициализатора 'init (coder :)' для класса

Это код:

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

Пожалуйста, предложите что-нибудь

Ответы:


208

вопрос

Это вызвано отсутствием инициализатора init?(coder aDecoder: NSCoder)на цели UIViewController. Этот метод необходим, потому что создание экземпляра UIViewControllerиз его UIStoryboardвызывает.

Чтобы увидеть, как мы инициализируем UIViewControllerиз a UIStoryboard, пожалуйста, посмотрите здесь

Почему это не проблема с Objective-C?

Потому что Objective-C автоматически наследует все необходимые UIViewControllerинициализаторы.

Почему Swift не наследует инициализаторы автоматически?

Swift по умолчанию не наследует инициализаторы из-за безопасности. Но он унаследует все инициализаторы из суперкласса, если все свойства имеют значение (или необязательно), а подкласс не определил никаких назначенных инициализаторов.


Решение

1. Первый способ

Внедрение init?(coder aDecoder: NSCoder)на цель вручнуюUIViewController

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

2. Второй метод

Удаление init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)на вашей цели UIViewControllerунаследует все необходимые инициализаторы от суперкласса, как Дэйв Вуд указал на свой ответ ниже



4
Спасибо за это. Быстрое продолжение ... Когда вы создаете файл TableViewController, Xcode уже включает init(style: UITableViewStyle) { super.init(style: style) // Custom initialization } Почему у нас может быть две функции инициализации? И есть идеи, почему Apple не включает 2-й init по умолчанию?
Тревор МакКендрик

Это не имеет ничего общего с iOS 7 или iOS 8. Это связано с тем, что Swift наследует инициализаторы!
Sulthan

public init (view: UIViewController, frame: CGRect) {self.viewController = view self.imageName = "" self.actionName = "" super.init (frame: frame)}
scrainie

Первый метод сработал! Моя динамическая таблица наконец заполнена динамическими ячейками !!! Все потому, что линия fatalError( "init(coder:) has not been implemented")остановила мое приложение.
Хосе Мануэль Абарка Родригес

26

Другой вариант, кроме @ 3r1d, - вместо этого удалить следующий метод init из вашего класса:

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

Включение этого метода init предотвращает наследование подкласса init(coder aDecoder: NSCoder!)от своего суперкласса. Не включая его, ваш класс унаследует оба.

Примечание. Для получения более подробной информации см. Сессия 403 WWDC 2014 «Промежуточное стремительное движение» около отметки 33:50.


Спасибо за указание на объяснение на Сессии 403. Но если дочерний класс имеет только удобные инициализаторы, тогда он унаследует инициализаторы суперкласса, верно?
jamiltz

1
Да. Вы только предотвращаете наследование методов инициализации суперкласса, если вы предоставляете свои собственные назначенные методы инициализации (те, которые вызывают супер-инициалы). Затем вы должны указать, какой из суперинтеретов поддерживать, добавив их в свой класс и просто вызвав супер версию (как в ответе @ 3r1d)
Дейв Вуд

Наличие только удобного init () без (обозначенного) init () в вашем дочернем классе приведет к ошибке компиляции. Это потому, что для удобства функция init () должна вызывать self.init () внутри определения функции.
Оми

@narumolPug Это неправильно. Вам не нужно включать обозначенные initметоды. Ваш дочерний класс унаследует их от суперкласса. Вы все еще можете позвонить, self.init()который выполнит супер версию.
Дейв Вуд

Точный момент видео можно найти здесь youtu.be/W1s9ZjDkSN0?t=2030
Мед

10

Для людей, имеющих ту же проблему с swift UICollectionViewCells, добавьте код, который @ 3r1d предложил для вашего пользовательского UICollectionViewCellкласса, а не для View Controller:

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

на какую UICollectionViewCell вы ссылаетесь? Инициирование с помощью кодера - это способ инициализации viewController
E-Riddie

Не в этом примере, но в случае, если у кого-то есть проблемы с этим (я сделал) ... если вы пытаетесь использовать UICollectionViewController, в вашем файле .swift вашей ячейки вы должны поместить init с кодером.
Ник Яп

2
Вам нужно добавлять этот код каждый раз, когда вы используете этот способ инстанцирования stackoverflow.com/questions/24035984/…
E-Riddie

3

Для тех, кому нужен код в Swift:

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

[Править] Это было для более старой версии Swift. Возможно, больше не работает.


3

У меня была эта проблема в программной ячейке collectionView, и хотя операционная система спрашивает о виртуальном канале, я все еще сталкиваюсь с этим вопросом при поиске ответа. Для меня проблема была у меня

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

реализовано так, что верхний ответ не сработал. В ячейке не было инициализатора:

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

Как только я добавил это, ошибка ушла


1

Вместо того, чтобы добавлять некоторые методы для обеспечения нормальной работы внутреннего механизма, я бы пошел с определением моих атрибутов как @lazy и инициализировал их прямо в области видимости класса.


Вы также можете объявить свою собственность как необязательную через ?.
Джулиан Б.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.