Utilice una class genérica como una vista personalizada en Interface Builder

Tengo una subclass personalizada de UIButton:

import UIKit @IBDesignable class MyButton: UIButton { var array : [String]? } 

Es IBDesignable y lo he configurado como la class personalizada para uno de los botones de mi storyboard. Me gustaría hacerlo genérico para que la matriz no tenga que ser uno de los objects String. Entonces probé esto:

 import UIKit @IBDesignable class MyButton<T>: UIButton { var array : [T]? } 

Sin embargo, no estoy seguro de cómo configurar esto como la class ahora en IB. Intenté poner MyButton<String> o MyButton<Int> , pero Interface Builder simplemente quita la porción de corchetes angulares y obtiene el siguiente error de compilation:

 Command /Applications/Xcode6-Beta4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift failed with exit code 254 

¿Hay alguna manera de usar una class personalizada genérica o no es compatible?

Interface Builder "habla" con su código a través del time de ejecución ObjC. Como tal, IB puede solo acceder a las características de su código que son representables en el time de ejecución de ObjC. ObjC no hace generics, por lo que no hay forma de que IB le diga al time de ejecución qué especialización de su class genérica usar. (Y una class genérica Swift no se puede crear una instancia sin una especialización, por lo que se MyButton un error al intentar instanciar un MyButton lugar de un MyButton<WhateverConcreteType> ).

(Puede reconocer el time de ejecución de ObjC en el trabajo en IB cuando rompe otras cosas: intentar usar una class Swift pura con salidas / acciones en una nib / storyboard da errores de time de ejecución sobre la introspección de ObjC. Dejando una connection conectada cuya statement de código correspondiente ha cambiado o se fue, da errores de time de ejecución sobre KVC. Et cetera).

Para ignorar los problemas de time de ejecución y ponerlo en una forma ligeramente diferente … volvamos a lo que IB necesita saber. Recuerde que el sistema de carga de nib es lo que crea una instancia en un storyboard en time de ejecución. Por lo tanto, incluso si las partes de la class que toman un parámetro de tipo genérico no son @IBInspectable , la punta todavía necesita saber qué class de especialización debe cargar su class genérica. Entonces, para que IB le permita usar classs genéricas para las vistas, el IB debería tener un lugar para que usted pueda identificar qué especialización de su class debe usar la punta. No es así, pero sería una gran request de características .

Mientras tanto, si todavía es útil para su class MyButton involucrar un cierto almacenamiento genérico, tal vez podría search tener la reference MyButton otra class que incluya almacenamiento genérico. (Tendría que hacerlo de tal manera que el tipo de dicho almacenamiento no se conozca en el time de compilation, de lo contrario, los parameters de tipo de esa otra class tendrían que propagarse de nuevo a MyButton ).

Tuve el mismo problema que primero quería usar la siguiente estructura:

 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 me las arreglé para 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 { requinetworking init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) super.object = MyObjectTypeOne() } } class SpecializedTableViewControllerTwo: GenericTableViewController { requinetworking init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) super.object = MyObjectTypeTwo() } } class GenericTableViewController : UIViewController { 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 salida de label muestra "object1" cuando enlace el SpecializedTableViewControllerOne como una class personalizada de mi controller de vista en el guión gráfico y "object2" si enlace a SpecializedTableViewControllerTwo