Swift: пользовательские инициализаторы ViewController

87

Как добавить пользовательские инициализаторы в UIViewControllerподклассы в Swift?

Я создал подкласс, UIViewControllerкоторый выглядит примерно так:

class MyViewController : UIViewController
{
    init(leftVC:UIViewController, rightVC:UIViewController, gap:Int)
    {
        self.leftVC = leftVC;
        self.rightVC = rightVC;
        self.gap = gap;

        super.init();

        setupScrollView();
        setupViewControllers();
    }
}

Когда я запускаю его, я получаю фатальную ошибку:

фатальная ошибка: использование нереализованного инициализатора init (nibName: bundle :) для класса MyApp.MyViewController

Я читал в другом месте, что при добавлении настраиваемого инициализатора необходимо также переопределить, init(coder aDecoder:NSCoder)поэтому давайте переопределим это initи посмотрим, что произойдет:

override init(coder aDecoder: NSCoder)
{
    super.init(coder: aDecoder);
}

Если я добавлю это, Xcode пожалуется на это self.leftVC is not initialized at super.init call. Так что я думаю, это тоже не может быть решением. Поэтому мне интересно, как мне правильно добавить настраиваемые инициализаторы в ViewControllerподкласс в Swift (поскольку в Objective-C это не проблема)?

БадминтонКошка
источник
Как вы пытаетесь создать экземпляр своего MyViewController?
Майк Поллард
Почему бы не создать все в viewDidLoad (), там вы можете инициализировать их так, как хотите
tudoricc
@MikePollard с dualViewCtrl = DualViewCtrl (leftVC: l, rightVC: r, gap: 50) ... Я уже узнал, что мне нужно использовать инициализатор initWithNib.
BadmintonCat
3
@tudoricc Потому что часто вам нужны свойства экземпляра, которые безопасно инициализируются в инициализаторе с заданными параметрами. Вы не можете сделать это в viewDidLoad, поскольку тогда не будет гарантировано, что свойства будут доступны, когда это необходимо.
BadmintonCat
Мне очень жаль, что я просто считаю viewDidLoad () инициализатором. спасибо за объяснение
tudoricc

Ответы:

124

Решил! Необходимо вызвать назначенный инициализатор, который в данном случае является init с nibName, очевидно ...

init(leftVC:UIViewController, rightVC:UIViewController, gap:Int)
{
    self.leftVC = leftVC
    self.rightVC = rightVC
    self.gap = gap

    super.init(nibName: nil, bundle: nil)

    setupScrollView()
    setupViewControllers()
}
БадминтонКошка
источник
31
Избавьтесь от этих уродливых
точек с
8
Мне нравятся точки с запятой. Они делают код менее двусмысленным, особенно с этими смехотворно многословными именами и подписями API Cocoa / Cocoa-Touch. Плохое решение дизайнеров Swift убрать их ИМХО.
BadmintonCat
25
ИМХО, если вы вводите символ, и это не влияет на скомпилированный двоичный файл, вам не следует его вводить :)
Сэм Соффес,
33
@SamSoffes, чтобы вы вообще не использовали (лишние) пробелы? И вы превращаете все символы в одиночные символы?
Виктор Жаленкас,
8
Эта дискуссия напомнила мне о табуляциях и
Аарон
13

Для более общего UIViewController вы можете использовать это начиная с Swift 2.0

init() {
    super.init(nibName: nil, bundle: nil)
}
Tr0yJ
источник
11

Не уверен, что вам удалось полностью решить эту проблему ... но в зависимости от того, как вы хотите, чтобы интерфейс вашего класса выглядел, и действительно ли вам нужны функции кодера, вы также можете использовать следующее:

convenience required init(coder aDecoder: NSCoder)
{
    //set some defaults for leftVC, rightVC, and gap
    self.init(leftVC, rightVC, gap)
}

Поскольку init:leftVC:rightVC:gapэто назначенный инициализатор, вы можете выполнить требование реализации init:coder, сделав его удобным инициализатором, который вызывает ваш назначенный инициализатор.

Это могло быть лучше, чем

override init(coder aDecoder: NSCoder)
{
    super.init(coder: aDecoder);
}

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

Wlingke
источник
8

Swift 5

Если вы хотите написать собственный инициализатор, UIViewControllerкоторый инициализируется с помощьюstoryBoard.instantiateViewController(withIdentifier: "ViewControllerIdentifier")

Вы можете написать собственный инициализатор только для Optionalсвойств.

class MyFooClass: UIViewController {
    var foo: Foo?

    init(with foo: Foo) {
        self.foo = foo
        super.init(nibName: nil, bundle: nil)
    }

    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.foo = nil
    }
}
emrcftci
источник