Неустранимая ошибка: использование не реализованного инициализатора '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.