ios interface-builder swift

ios - protocolo swift, la propiedad IBOutlet no puede tener un tipo que no sea un objeto



interface-builder (6)

Me gustaría conectar a un delegado rápido personalizado en IB. El delegado es un objeto que implementa un cierto protocolo en swift.

protocol ThumbnailTableViewCellDelegate { func cellWasTouched(thumbnail: Bool, cell: UITableViewCell) } class ThumbnailTableViewCell: UITableViewCell { @IBOutlet var thumbnailTableViewCellDelegate: ThumbnailTableViewCellDelegate? }

desafortunadamente, el compilador se queja con:

error: ''IBOutlet'' property cannot have non-object type ''ThumbnailTableViewCellDelegate'' @IBOutlet var thumbnailTableViewCellDelegate: ThumbnailTableViewCellDelegate? ^~~~~~~~~


Los IBOutlets son para indicar un puntero a un objeto almacenado en un archivo de plumilla (o guión gráfico). Un protocolo no es un objeto, por lo tanto, no puede tener uno en un archivo de plumilla. Haga que el tipo de var de IBOutlet sea el tipo del objeto real que tiene en la punta.


No es ideal, pero una opción es hacer algo como esto:

@IBOutlet var objectType: NSObject! private var conformingObject: SomeProtocol { return objectType as SomeProtocol }

Asegúrese de que su tipo de objectType ajuste a SomeProtocol o las cosas explotarán


Puede conectar sus propios protocolos en IB con esta solución. Es un problema conocido con Xcode, por lo que probablemente se resolverá algún día. Hasta entonces:

  1. Declare al delegado como AnyObject - @IBOutlet var delegate: AnyObject!
  2. Conecte el delegado en Interface Builder
  3. Cambie el tipo de salida a su protocolo, por ejemplo, @IBOutlet var delegate: MyDelegate

Esto funciona para mi


Tiene sentido que IB requiera AnyObject, en lugar de su protocolo particular. El objeto al que desea conectarse probablemente, pero no necesariamente cumple con el protocolo, y el protocolo puede tener opciones, por lo que:

Haz tu protocolo de esta manera:

@objc public protocol HexViewDataSource: NSObjectProtocol { @objc optional func dataAtOffset (_ hexView: HexView, offset: UInt64, length: Int)-> Data? @objc optional func dataLength (_ hexView: HexView) -> UInt64 }

Declara en tu clase como esta, por ejemplo:

@IBOutlet weak open var dataSource: AnyObject?

Y cuando llegue a usarlo, verifique que cumpla con el protocolo y que existan los opcionales, como esto:

if let dataSource = dataSource as? HexViewDataSource, let dfr = dataSource.dataAtOffset { setRowData(offset: offset, data: dfr (self, offset, bytesPerRow)) }


Una variable de tipo de protocolo podría no ser un objeto, porque las estructuras y las enumeraciones también pueden ajustarse a los protocolos. Para asegurarse de que un protocolo solo pueda ajustarse a las clases, puede declarar el protocolo con @class_protocol .


@objc declarar su protocolo ThumbnailTableViewCellDelegate como @objc :

@objc protocol ThumbnailTableViewCellDelegate { func cellWasTouched(thumbnail: Bool, cell: UITableViewCell) }

Esto se debe a que @IBOutlet declara la variable como weak , que solo funciona con objetos. No estoy seguro de por qué no puedes simplemente decir que el protocolo se ajusta a AnyObject , quizás sea un error Swift.