Con el siguiente código trato de definir una clase de modelo simple y su inicializador fallido, que toma un diccionario (json-) como parámetro. El inicializador debería regresar nil
si el nombre de usuario no está definido en el json original.
1. ¿Por qué no se compila el código? El mensaje de error dice:
Todas las propiedades almacenadas de una instancia de clase deben inicializarse antes de devolver nil de un inicializador.
Eso no tiene sentido. ¿Por qué debería inicializar esas propiedades cuando planeo regresar nil
?
2. ¿Es mi enfoque el correcto o habría otras ideas o patrones comunes para lograr mi objetivo?
class User: NSObject {
let userName: String
let isSuperUser: Bool = false
let someDetails: [String]?
init?(dictionary: NSDictionary) {
if let value: String = dictionary["user_name"] as? String {
userName = value
}
else {
return nil
}
if let value: Bool = dictionary["super_user"] as? Bool {
isSuperUser = value
}
someDetails = dictionary["some_details"] as? Array
super.init()
}
}
swift
object-initializers
Kai Huppmann
fuente
fuente
canSetCalculableProperties
parámetro booleano que permite a mi inicializador calcular propiedades que pueden o no pueden crearse sobre la marcha. Por ejemplo, sidateCreated
falta una clave y puedo establecer la propiedad sobre la marcha porque elcanSetCalculableProperties
parámetro es verdadero, simplemente lo configuro en la fecha actual.Respuestas:
Actualización: del registro de cambios de Swift 2.2 (publicado el 21 de marzo de 2016):
Para Swift 2.1 y versiones anteriores:
Según la documentación de Apple (y el error de su compilador), una clase debe inicializar todas sus propiedades almacenadas antes de regresar
nil
de un inicializador que falla:Nota: En realidad, funciona bien para estructuras y enumeraciones, pero no para clases.
La forma sugerida de manejar las propiedades almacenadas que no se pueden inicializar antes de que falle el inicializador es declararlas como opcionales implícitamente desempaquetadas.
Ejemplo de los documentos:
En su caso, sin embargo, sólo tiene que definir
userName
como unString!
problema no se soluciona el error de compilación, ya que todavía tiene que preocuparse sobre la inicialización de las propiedades de su clase base,NSObject
. Afortunadamente, conuserName
definido como aString!
, puede llamarsuper.init()
antesreturn nil
que usted, lo que iniciará suNSObject
clase base y solucionará el error de compilación.fuente
Product
clase) no puede desencadenar una falla de inicialización antes de asignar un valor específico, aunque los documentos dicen que sí. Los documentos no están sincronizados con la última versión de Swift. En su lugar, se recomienda hacerlovar
por ahoralet
. fuente: Chris Lattner .Según Chris Lattner, esto es un error. Esto es lo que dice:
Fuente
EDITAR:
Swift ahora es de código abierto y, de acuerdo con este registro de cambios , ahora está arreglado en instantáneas de swift 2.2
fuente
Acepto que la respuesta de Mike S es la recomendación de Apple, pero no creo que sea la mejor práctica. El objetivo de un sistema de tipos fuerte es mover los errores de tiempo de ejecución al tiempo de compilación. Esta "solución" frustra ese propósito. En mi humilde opinión, sería mejor seguir adelante e inicializar el nombre de usuario
""
y luego verificarlo después de super.init (). Si se permiten nombres de usuario en blanco, establezca una marca.fuente
Otra forma de eludir la limitación es trabajar con funciones de clase para realizar la inicialización. Es posible que incluso desee mover esa función a una extensión:
Usarlo se convertiría en:
fuente
Aunque Swift 2.2 se ha lanzado y ya no tiene que inicializar completamente el objeto antes de fallar el inicializador, debe mantener sus caballos hasta que se corrija https://bugs.swift.org/browse/SR-704 .
fuente
Descubrí que esto se puede hacer en Swift 1.2
Hay algunas condiciones:
Ejemplo:
fuente
Extracto de: Apple Inc. “ El lenguaje de programación Swift. ”IBooks. https://itun.es/sg/jEUH0.l
fuente
Puede utilizar el inicio de conveniencia :
fuente