Swift: inicializadores de ViewController personalizados

87

Como você adiciona inicializadores personalizados a UIViewControllersubclasses em Swift?

Eu criei uma subclasse de UIViewControllerque se parece com isto:

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

        super.init();

        setupScrollView();
        setupViewControllers();
    }
}

Quando o executo, recebo um erro fatal:

erro fatal: uso de inicializador não implementado 'init (nibName: bundle :)' para a classe 'MyApp.MyViewController'

Eu li em outro lugar que, ao adicionar um inicializador personalizado, é necessário também sobrescrever, init(coder aDecoder:NSCoder)então vamos sobrescrever isso inite ver o que acontece:

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

Se eu adicionar isso, o Xcode reclamará disso self.leftVC is not initialized at super.init call. Então acho que essa também não pode ser a solução. Então, eu me pergunto como posso adicionar inicializadores personalizados corretamente a uma ViewControllersubclasse em Swift (já que em Objective-C isso parece não ser um problema)?

BadmintonCat
fonte
Como você está tentando instanciar o seu MyViewController?
Mike Pollard de
Por que não instanciar tudo em viewDidLoad (), lá você pode inicializá-los da maneira que quiser
tudoricc
@MikePollard com dualViewCtrl = DualViewCtrl (leftVC: l, rightVC: r, gap: 50) ... Eu já descobri que preciso usar o inicializador initWithNib.
BadmintonCat
3
@tudoricc Porque freqüentemente você deseja propriedades de instância que são inicializadas com segurança no inicializador com parâmetros fornecidos. Você não pode fazer isso em viewDidLoad, pois não seria garantido que as propriedades estarão disponíveis quando necessário.
BadmintonCat
Lamento apenas que, em minha mente, vejo viewDidLoad () como um inicializador. obrigado pela explicação
tudoricc

Respostas:

124

Resolvi-o! Deve-se chamar o inicializador designado que neste caso é o init com nibName, obviamente ...

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

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

    setupScrollView()
    setupViewControllers()
}
BadmintonCat
fonte
31
Livre-se desses pontos-e-vírgulas feios :)
MobileMon
8
Eu gosto de ponto e vírgula. Eles tornam o código menos ambíguo, especialmente com aqueles nomes e assinaturas de API Cocoa / Cocoa-Touch ridiculamente verborrágicos. Má decisão dos designers do Swift para removê-los IMHO.
BadmintonCat
25
IMHO, se você digitar um caractere e ele não afetar o binário compilado, você não deve digitá-lo :)
Sam Soffes
32
@SamSoffes, então você não usa nenhum espaço em branco (extra)? E você ofusca todos os símbolos para serem caracteres únicos?
Victor Jalencas
8
Esta discussão me lembra tabs vs espaços no Vale do Silício
Aaron,
13

Para um UIViewController mais genérico, você pode usá-lo a partir do Swift 2.0

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

Não tenho certeza se você conseguiu resolver isso totalmente ... mas dependendo de como você deseja que a interface de sua classe pareça e se você realmente precisa ou não da funcionalidade do codificador, você também pode usar o seguinte:

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

Como init:leftVC:rightVC:gapé um inicializador designado, você pode cumprir o requisito de implementação init:codertornando-o um inicializador de conveniência que chama seu inicializador designado.

Isso poderia ser melhor do que

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

porque se você precisar inicializar algumas propriedades, será necessário reescrevê-las.

Wlingke
fonte
8

Swift 5

Se você quiser escrever um inicializador personalizado para o UIViewControllerqual é inicializado comstoryBoard.instantiateViewController(withIdentifier: "ViewControllerIdentifier")

Você pode escrever o inicializador personalizado apenas para Optionalpropriedades.

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
fonte