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?
Mike Pollard

Чому б не створити екземпляр у всьому viewDidLoad (), там ви можете їх ініціалізувати як завгодно
tudoricc

@MikePollard with dualViewCtrl = DualViewCtrl (leftVC: l, rightVC: r, gap: 50) ... Я вже з'ясував, що мені потрібно використовувати ініціалізатор initWithNib.
BadmintonCat

3
@tudoricc Оскільки часто вам потрібні властивості екземпляра, які безпечно ініціалізуються в ініціалізаторі із заданими параметрами. Ви не можете цього зробити у viewDidLoad, оскільки з цього часу не буде гарантовано, що властивості доступні у разі потреби.
BadmintonCat

Мені шкода лише те, що на мою думку я бачу viewDidLoad () як ініціатор.
подяка

Відповіді:


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 какао / какао-сенсор. Помилкове рішення дизайнерів Свіфта вилучити їх з ІМХО.
BadmintonCat

25
ІМХО, якщо ви вводите символ і це не впливає на скомпільований двійковий файл, ви не повинні його вводити :)
Сем Софф

33
@SamSoffes, щоб ви взагалі не використовували (зайві) пробіли? І ви затуманюєте всі символи окремими символами?
Віктор Яленкас,

8
Ця дискусія нагадує мені вкладки та пробіли в Силіконовій долині
Аарон,

13

Для більш загального UIViewController ви можете використовувати це, починаючи з Swift 2.0

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

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);
}

тому що якщо вам потрібно ініціалізувати деякі властивості, то вам доведеться їх переписати.


8

Стрімкий 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
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.