Почему я не могу вызвать super.init() по умолчанию для UIViewController в Swift?

Я не использую UIViewController из раскадровки, и я хочу иметь пользовательскую функцию init, в которой я передаю NSManagedObjectID какого-либо объекта. Я просто хочу вызвать super.init(), как в Objective-C. Как это:

init(objectId: NSManagedObjectID) {
    super.init()
}

Но я получаю следующую ошибку компилятора:

Необходимо вызвать назначенный инициализатор суперкласса UIViewController.

Могу ли я просто не делать этого больше?


person SirRupertIII    schedule 07.06.2014    source источник


Ответы (4)


Назначенным инициализатором для UIViewController является initWithNibName:bundle:. Вы должны называть это вместо этого.

См. http://www.bignerdranch.com/blog/real-iphone-crap-2-initwithnibnamebundle-is-the-designated-initializer-of-uiviewcontroller/

Если у вас нет пера, передайте nil для nibName (bundle также не является обязательным). Затем вы можете создать собственное представление в loadView или добавить подпредставления в self.view в viewDidLoad, как и раньше.

person occulus    schedule 07.06.2014
comment
Так что в настоящее время я не могу создать пользовательский метод инициализации в подклассе UIViewController, который не из пера? - person SirRupertIII; 07.06.2014
comment
Ааа, спасибо!! Я перешел на название пера. - person SirRupertIII; 07.06.2014
comment
Одного переопределения initWithNibName:bundle: недостаточно; компилятор выдаст ошибку и предложит вам также реализовать (обязательно) initWithCoder:. Я предполагаю, что оба являются назначенными инициализаторами? Но только withCoder помечается как требуемое в swift... - person Nicolas Miari; 16.07.2015
comment
О, после небольшого копания выясняется, что initWithCoder: исходит из протокола NSCoding... Я до сих пор не могу понять, какова его роль в инициализации экземпляра UIViewController, является ли он назначенным инициализатором UIViewController или любого из его суперклассов.. . - person Nicolas Miari; 16.07.2015
comment
Спасибо! Для быстрого копирования/вставки просто вызовите это после установки свойств let, если они есть: super.init(nibName: nil, bundle: nil). - person Ferran Maylinch; 29.03.2017
comment
Init With coder используется, когда вам нужно восстановить состояние. Когда вы сохраняете состояние контроллера представления с помощью функции восстановления состояния, кодер вернет значения, которые вы сохранили при сохранении состояния. Оттуда вы можете перестроить контроллер представления в его последнее начальное состояние, когда вы закрыли приложение. Итак, для пользователя это то, с чего он остановился - person Esko918; 26.11.2017

Другое хорошее решение — объявить ваш новый инициализатор как инициализатор convenience следующим образом:

convenience init( objectId : NSManagedObjectID ) {
    self.init()

    // ... store or user your objectId
}

Если вы вообще не объявляете назначенных инициализаторов в своем подклассе, они наследуются автоматически, и вы можете использовать self.init() в своем удобном инициализаторе.

В случае UIViewController метод инициализации по умолчанию будет вызывать init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) с nil для обоих аргументов (Command-Click на UIViewController даст вам эту информацию).

TL;TR: если вы предпочитаете программно работать с UIViewControllers, вот полный рабочий пример, который добавляет новый инициализатор с настраиваемым аргументом:

class MyCustomViewController: UIViewController {
    var myString: String = ""

    convenience init( myString: String ) {
        self.init()

        self.myString = myString
    }
}
person Klaas    schedule 15.08.2014
comment
Это более элегантное решение, которое работает в любом общем случае. - person Ciprian; 18.03.2015
comment
Я попытался сделать это в расширении, и оно рекурсивно вызвало себя. - person Danyal Aytekin; 08.05.2015
comment
@DanyalAytekin, когда вы предоставляете свой код как суть, я могу сказать вам, почему. - person Klaas; 13.05.2015
comment
Хитрость этого ответа заключается в том, что myString установлено на "", поэтому init не требуется. Это решение разваливается, если вы не хотите использовать начальное значение, и в этом случае вам нужно использовать self.init(nibName: nil, bundle:nil) - person Dan Rosenstark; 07.06.2015
comment
@Yar, или вы сделаете свойство myString необязательным - person Klaas; 10.06.2015
comment
@Klaas да: моя проблема в том, что я использовал инициализаторы ТОЛЬКО, чтобы избежать необязательных параметров и заставить мой код компилироваться. - person Dan Rosenstark; 10.06.2015
comment
@DanyalAytekin (и другие): см. мой ответ на этот связанный вопрос, чтобы решить проблему бесконечной рекурсии. - person Jamie Birch; 20.04.2017

Чтобы улучшить ответ occulus:

init() {
     super.init(nibName: nil, bundle: nil)
}
person Vyacheslav    schedule 29.09.2017

Обновление: добавьте ссылку

https://developer.apple.com/documentation/uikit/uiviewcontroller/1621359-init

Согласно документации для iOS, назначенным инициализатором для UIViewController является initWithNibName: bundle:.

Если вы создаете подкласс UIViewController, вы должны вызвать суперреализацию этого метода, даже если вы не используете NIB.

Вы можете сделать это следующим образом:

init(objectId : NSManagedObjectID) {

    super.init(nibName: (xib's name or nil'), bundle: nil)

   // other code...
}

или

Объявите новый инициализатор как удобный инициализатор:

 convenience init( objectId : NSManagedObjectID ) {

    self.init()

     // other code...

}

person NcNc    schedule 24.06.2017
comment
Вы должны ссылаться на оригинал для указания авторства, а не оставлять его в качестве скриншота. - person Nathan Tuggy; 24.06.2017
comment
@NathanTuggy Нет, не должен. Ссылки имеют функцию истечения срока действия или переноса. Кто хочет видеть ошибку 404 вместо информации, которую он ищет? - person mykolaj; 15.03.2018
comment
@mykolaj: Информация уже здесь, в этом ответе. (В противном случае я бы пометил для удаления как ответ только по ссылке.) Но атрибуция также важна, чтобы любой, кто читает это, мог узнать, откуда он взялся, и указать их. Скриншот для этого не подходит, а ссылка подойдет. Если ссылка гниет, что ж, это прискорбно, но вы не можете сказать мне, что это хуже ситуации, чем вообще отсутствие каких-либо кредитов. Возражения, которые SO имеет к ответам только по ссылкам, относятся к ответам только по ссылке. Не до ссылок. Ссылка а также информация является желаемой формулировкой. - person Nathan Tuggy; 15.03.2018
comment
@NathanTuggy Я только что добавил ссылку. Спасибо за напоминание - person NcNc; 22.03.2018