ios - not - ibinspectable swift 4
Utilice una clase genérica como una vista personalizada en Interface Builder (2)
Interface Builder "habla" con su código a través del tiempo de ejecución de ObjC. Como tal, IB solo puede acceder a las funciones de su código que se pueden representar en el tiempo de ejecución de ObjC. ObjC no hace genéricos, por lo que no hay una manera de que IB le diga al tiempo de ejecución qué especialización de su clase genérica debe usar. (Y no se puede crear una instancia de una clase genérica Swift sin una especialización, por lo que se MyButton
un error al intentar crear una instancia de MyButton
lugar de MyButton<WhateverConcreteType>
).
(Puede reconocer el tiempo de ejecución de ObjC en el trabajo en IB cuando rompe otras cosas: el intento de usar una clase Swift pura con tomas / acciones en una pluma / guión gráfico produce errores de tiempo de ejecución sobre la introspección de ObjC. Dejando una salida conectada cuya declaración de código correspondiente ha cambiado o desaparecido da errores de tiempo de ejecución sobre KVC. Etcétera.)
Para ignorar los problemas de tiempo de ejecución y ponerlo de una manera ligeramente diferente ... volvamos a lo que IB necesita saber. Recuerde que el sistema de carga de plumillas es lo que crea una instancia de cualquier cosa en un guión gráfico en tiempo de ejecución. Entonces, incluso si las partes de su clase que toman un parámetro de tipo genérico no son @IBInspectable
, la punta necesita saber qué especialización de su clase genérica debe cargar. Por lo tanto, para que IB le permita usar clases genéricas para las vistas, IB debería tener un lugar para que usted identifique qué especialización de su clase debe usar la pluma. No lo hace, pero eso sería una gran solicitud de características .
Mientras tanto, si sigue siendo útil que su clase MyButton
implique algún almacenamiento genérico, tal vez podría considerar que MyButton
referencia a otra clase que incluya almacenamiento genérico. (Tendría que hacerlo de tal manera que no se conozca el tipo de dicho almacenamiento en el momento de la compilación; de lo contrario, los parámetros de tipo de esa otra clase tendrían que propagarse de nuevo a MyButton
).
Tengo una subclase personalizada de UIButton:
import UIKit
@IBDesignable
class MyButton: UIButton {
var array : [String]?
}
Es IBDesignable y la he configurado como la clase personalizada para uno de los botones de mi guión gráfico. Me gustaría hacerlo genérico para que la matriz no tenga que ser uno de los objetos String. Por lo tanto, he intentado esto:
import UIKit
@IBDesignable
class MyButton<T>: UIButton {
var array : [T]?
}
Sin embargo, no estoy seguro de cómo establecer esto como la clase ahora en IB. Intenté poner MyButton<String>
o MyButton<Int>
, pero Interface Builder solo elimina la parte de los corchetes angulares y obtiene el siguiente error de compilación:
Command /Applications/Xcode6-Beta4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift failed with exit code 254
¿Hay alguna forma de usar una clase personalizada genérica o no es compatible?
Tuve el mismo problema que el primero que quise usar:
import UIKit
protocol MyDataObjectProtocol{
var name:String { get}
}
class MyObjectTypeOne:MyDataObjectProtocol{
var name:String { get { return "object1"}}
}
class MyObjectTypeTwo:MyDataObjectProtocol{
var name:String { get { return "object2"}}
}
class SpecializedTableViewControllerOne: GenericTableViewController<MyObjectTypeOne> {
}
class SpecializedTableViewControllerTwo: GenericTableViewController<MyObjectTypeTwo> {
}
class GenericTableViewController<T where T:MyDataObjectProtocol>: UITableViewController {
// some common code I don''t want to be duplicated in
// SpecializedTableViewControllerOne and SpecializedTableViewControllerTwo
// and that uses object of type MyDataObjectProtocol.
}
Pero como se explicó en la respuesta anterior, esto no es posible. Así que logré trabajar con el siguiente código:
import UIKit
protocol MyDataObjectProtocol{
var name:String { get}
}
class MyObjectTypeOne:MyDataObjectProtocol{
var name:String { get { return "object1"}}
}
class MyObjectTypeTwo:MyDataObjectProtocol{
var name:String { get { return "object2"}}
}
class SpecializedTableViewControllerOne: GenericTableViewController {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
super.object = MyObjectTypeOne()
}
}
class SpecializedTableViewControllerTwo: GenericTableViewController {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
super.object = MyObjectTypeTwo()
}
}
class GenericTableViewController : UITableViewController {
var object : MyDataObjectProtocol?
@IBOutlet weak var label: UILabel!
override func viewDidLoad() {
label.text = object?.name
}
// some common code I don''t want to be duplicated in
// SpecializedTableViewControllerOne and SpecializedTableViewControllerTwo
// and that uses object of type MyDataObjectProtocol.
}
Ahora mi etiqueta de salida muestra "object1" cuando vinculo SpecializedTableViewControllerOne
como una clase personalizada de mi controlador de vista en el guión gráfico y "object2" si vinculo a SpecializedTableViewControllerTwo