Estoy aprendiendo el desarrollo de iOS a partir de un curso en línea y cada vez que hago una vista personalizada (celda de vista de tabla personalizada, celda de vista de colección, etc.) el instructor siempre implementa este inicializador:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
¿Por qué exactamente siempre tengo que llamar a esto? ¿Qué hace? ¿Puedo poner propiedades dentro del init?
NSCoding
entonces necesita implementar este inicializador, ya que se requiere de las clases que implementanNSCoding
. Debe llamar al menos al método init de la superclase. SiNSCoder
contiene propiedades codificadas para su clase, puede usar este método para recuperarlasRespuestas:
Comenzaré esta respuesta desde la dirección opuesta: ¿qué pasa si desea guardar el estado de su vista en el disco? Esto se conoce como serialización . Lo contrario es la deserialización : restaurar el estado del objeto desde el disco.
El
NSCoding
protocolo define dos métodos para serializar y deserializar objetos:Entonces, ¿por qué es necesario en tu clase personalizada? La respuesta es Interface Builder. Cuando arrastra un objeto a un guión gráfico y lo configura, Interface Builder serializa el estado de ese objeto en el disco y luego lo deserializa cuando el guión gráfico aparece en la pantalla. Necesita decirle a Interface Builder cómo hacerlo. Como mínimo, si no agrega ninguna propiedad nueva a su subclase, simplemente puede pedirle a la superclase que haga el empaque y desempaque por usted, de ahí el
super.init(coder: aDecoder)
llamada. Si su subclase es más compleja, debe agregar su propio código de serialización y deserialización para la subclase.Esto contrasta con el enfoque de Visual Studio, que consiste en escribir código en un archivo oculto para crear el objeto en tiempo de ejecución.
fuente
init(coder aCoder : NSCoder)
?awakeFromNib
, no funcionará.awakeFromNib
se invoca en tiempo de ejecución . Todo lo que haga en Interface Builder es durante el tiempo de diseño . Para llevar lo que ha hecho en tiempo de diseño al tiempo de ejecución esencodeWithCoder
(guardar) yinit(coder:)
(cargar)awakeFromNib
oinitWIthFrame
El requisito de implementar ese inicializador es una consecuencia de dos cosas:
El principio de sustitución de Liskov . Si S es una subclase de T (por ejemplo,
MyViewController
es una subclase deViewController
), entonces los objetos S (instancias deMyViewController
) deben poder sustituirse dondeViewController
se esperan objetos T (instancias de ).Los inicializadores no se heredan en Swift si algún inicializador se define explícitamente en la subclase. Si se proporciona explícitamente un inicializador, todos los demás deben proporcionarse explícitamente (que luego puede simplemente llamar
super.init(...)
). Consulte esta pregunta para conocer la justificación. Está en Java, pero todavía se aplica.En el punto 1, todo lo que
ViewController
puede hacer el original ,MyViewController
subclase debería poder hacerlo. Una de esas cosas es poder inicializarse a partir de un determinadoNSCoder
. En el punto 2, suMyViewController
subclase no hereda automáticamente esta habilidad. Por lo tanto, debe proporcionar manualmente el inicializador que cumpla con este requisito. En este caso, solo necesita delegar hasta la superclase, para que haga lo que normalmente haría.fuente