Swift: inicializadores de ViewController personalizados

87

¿Cómo se agregan inicializadores personalizados a las UIViewControllersubclases en Swift?

He creado una subclase UIViewControllerque se parece a esto:

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

        super.init();

        setupScrollView();
        setupViewControllers();
    }
}

Cuando lo ejecuto, aparece un error fatal:

error fatal: uso del inicializador no implementado 'init (nibName: bundle :)' para la clase 'MyApp.MyViewController'

He leído en otro lugar que cuando se agrega un inicializador personalizado, también se debe anular, init(coder aDecoder:NSCoder)así que anulemos eso inity veamos qué sucede:

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

Si agrego esto, Xcode se queja de eso self.leftVC is not initialized at super.init call. Así que supongo que tampoco puede ser la solución. Entonces, me pregunto cómo puedo agregar inicializadores personalizados correctamente a una ViewControllersubclase en Swift (ya que en Objective-C esto parece no ser un problema).

BádmintonGato
fuente
¿Cómo intentas crear una instancia de tu MyViewController?
Mike Pollard
¿Por qué no instantiate todo en viewDidLoad (), no se puede inicializar ellos de la manera que desee
tudoricc
@MikePollard con dualViewCtrl = DualViewCtrl (leftVC: l, rightVC: r, gap: 50) ... Ya descubrí que necesito usar el inicializador initWithNib.
BadmintonCat
3
@tudoricc Porque a menudo desea propiedades de instancia que se inicialicen de forma segura en el inicializador con los parámetros dados. No puede hacer eso en viewDidLoad ya que entonces no se garantizaría que las propiedades estén disponibles cuando sea necesario.
BadmintonCat
Lo siento es solo que en mi mente veo viewDidLoad () como un inicializador. gracias por la explicación
tudoricc

Respuestas:

124

¡Resuelto! Uno tiene que llamar al inicializador designado que en este caso es el init con 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()
}
BádmintonGato
fuente
31
Deshazte de esos feos puntos y coma :)
MobileMon
8
Me gustan los puntos y comas. Hacen que el código sea menos ambiguo, especialmente con esos nombres y firmas de API de Cocoa / Cocoa-Touch ridículamente detallados. Mala decisión de los diseñadores de Swift para eliminarlos en mi humilde opinión.
BadmintonCat
25
En mi humilde opinión, si escribe un carácter y no afecta el binario compilado, no debe escribirlo :)
Sam Soffes
32
@SamSoffes para que no use espacios en blanco (extra) en absoluto? ¿Y confunde todos los símbolos para que sean caracteres únicos?
Victor Jalencas
8
Esta discusión me recuerda a las pestañas frente a los espacios en Silicon Valley
Aaron
13

Para un UIViewController más genérico, puede usar esto a partir de Swift 2.0

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

No estoy seguro si logró resolver esto por completo ... pero dependiendo de cómo desee que se vea la interfaz de su clase y si realmente necesita o no la funcionalidad del codificador, también puede usar lo siguiente:

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

Dado que init:leftVC:rightVC:gapes un inicializador designado, puede cumplir con el requisito de implementación init:coderconvirtiéndolo en un inicializador de conveniencia que llame a su inicializador designado.

Esto podría ser mejor que

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

porque si necesita inicializar algunas propiedades, deberá volver a escribirlas.

wlingke
fuente
8

Rápido 5

Si desea escribir un inicializador personalizado en el UIViewControllerque se inicializa constoryBoard.instantiateViewController(withIdentifier: "ViewControllerIdentifier")

Puede escribir un inicializador personalizado solo para Optionalpropiedades.

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
fuente