Usar ''self'' en funciones de extensión de clase en Swift
(2)
Creo que la expresión condicional que está buscando es
topLevelObject.dynamicType == self
Combinando esto con
unsafeBitCast
(que, según la propia documentación de Apple, "Rompe las garantías del sistema de tipos de Swift")
, podemos
topLevelObject
forzosamente
topLevelObject
para
topLevelObject
self
.
Esto
debería
ser seguro porque ya nos aseguramos de que
topLevelObject
sea del mismo tipo que
self
Esta es una forma de sortear el método auxiliar utilizando los genéricos que describió Martin R.
extension UIView {
class func instantiateFromNib() -> Self? {
let bundle = NSBundle.mainBundle().loadNibNamed("CustomViews", owner: nil, options: nil)
for topLevelObject in topLevelObjects {
if topLevelObject.dynamicType == self {
return unsafeBitCast(topLevelObject, self)
}
}
return nil
}
}
Tenga en cuenta que Apple también dice en su documentación para
unsafeBitCast
:
Casi siempre hay una mejor manera de hacer cualquier cosa.
¡Así que ten cuidado!
Estoy buscando poder extraer una instancia de una subclase UIView de un Nib.
Me gustaría poder llamar a MyCustomView.instantiateFromNib () y tener una instancia de MyCustomView. Estoy casi listo para portar el código de Objective-C que tengo a través del encabezado de puente, pero pensé que primero probaría el enfoque idiomático. Eso fue hace dos horas.
extension UIView {
class func instantiateFromNib() -> Self? {
let topLevelObjects = NSBundle.mainBundle().loadNibNamed("CustomViews", owner: nil, options: nil)
for topLevelObject in topLevelObjects {
if (topLevelObject is self) {
return topLevelObject
}
}
return nil
}
}
Ahora
if (topLevelObject is self) {
está mal porque "Tipo esperado después de ''is''".
Lo que he intentado después de eso muestra mucho sobre lo que no entiendo sobre el sistema de tipos Swift.
-
if (topLevelObject is Self) {
-
if (topLevelObject is self.dynamicType) {
-
if (topLevelObject is self.self) {
- Un millón de otras variaciones que ni siquiera están mal .
Cualquier idea es apreciada.
Uso del enfoque de
¿Cómo puedo crear instancias de subclases de objetos administrados en una extensión NSManagedObject Swift?
puede definir un método auxiliar genérico que infiere el tipo de
self
desde el contexto de llamada:
extension UIView {
class func instantiateFromNib() -> Self? {
return instantiateFromNibHelper()
}
private class func instantiateFromNibHelper<T>() -> T? {
let topLevelObjects = NSBundle.mainBundle().loadNibNamed("CustomViews", owner: nil, options: nil)
for topLevelObject in topLevelObjects {
if let object = topLevelObject as? T {
return object
}
}
return nil
}
}
Esto compila y funciona como se esperaba en mi prueba rápida.
Si
MyCustomView
es su subclase de
UIView
entonces
if let customView = MyCustomView.instantiateFromNib() {
// `customView` is a `MyCustomView`
// ...
} else {
// Not found in Nib file
}
le da una instancia de
MyCustomView
, y el tipo se infiere automáticamente.
Actualización para Swift 3:
extension UIView {
class func instantiateFromNib() -> Self? {
return instantiateFromNibHelper()
}
private class func instantiateFromNibHelper<T>() -> T? {
if let topLevelObjects = Bundle.main.loadNibNamed("CustomViews", owner: nil, options: nil) {
for topLevelObject in topLevelObjects {
if let object = topLevelObject as? T {
return object
}
}
}
return nil
}
}