Reneli
Reneli

Reputation: 1856

swift protocol, IBOutlet property cannot have non-object type

I would like to wire up a custom swift delegate in IB. The delegate is an object that implements a certain protocol in swift.

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

class ThumbnailTableViewCell: UITableViewCell {
    @IBOutlet var thumbnailTableViewCellDelegate: ThumbnailTableViewCellDelegate?
}

unfortunately, the compiler complains with:

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

Upvotes: 18

Views: 15020

Answers (7)

Fattie
Fattie

Reputation: 12582

For 2023 ...

You simply have to add @objcbefore the protocol definition.

You do not have to make ANY changes in the view controllers.

Example:

@objc protocol VideoControls {
    var playButton: UIButton! { get }
    var pauseButton: UIButton! { get }
    var timeText: UILabel! { get }

and then in a view controller ...

class CompactPlayer: UIViewController, VideoControls {
    @IBOutlet var playButton: UIButton!
    @IBOutlet var pauseButton: UIButton!
    @IBOutlet var timeText: UILabel!

and

class FullScreenPlayer: UIViewController, VideoControls {
    @IBOutlet var playButton: UIButton!
    @IBOutlet var pauseButton: UIButton!
    @IBOutlet var timeText: UILabel!

That's it.

Upvotes: 0

Colin Wilson
Colin Wilson

Reputation: 271

It kind of makes sense that IB requires AnyObject, rather than your particular protocol. The object you want to connect to probably, but not necessarily conforms to the protocol, and the protocol may have optionals - so:

Make your protocol like this:

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

Declare it in your class like this, for instance:

@IBOutlet weak open var dataSource: AnyObject?

And when you come to use it, check that it conforms to the protocol and that the optionals exist - like this:

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

Upvotes: 0

Morten J
Morten J

Reputation: 914

You can in connect your own protocols in IB with this workaround. It's a known issue with Xcode, so will probably be solved one day. Until then:

  1. Declare the delegate as an AnyObject - @IBOutlet var delegate:AnyObject!
  2. Connect the delegate in Interface Builder
  3. Change the outlet's type to your protocol, e.g. @IBOutlet var delegate:MyDelegate

This works for me.

Upvotes: 13

Adam Waite
Adam Waite

Reputation: 18845

Not ideal, but an option is to do something like this:

@IBOutlet var objectType: NSObject!

private var conformingObject: SomeProtocol {
  return objectType as SomeProtocol
}

Got to make sure your objectType conforms to SomeProtocol or things will explode

Upvotes: 1

newacct
newacct

Reputation: 122419

A variable of protocol type might not be an object, because structs and enums can conform to protocols too. To ensure that a protocol can only be conformed to by classes, you can declare the protocol with @class_protocol.

Upvotes: 0

Nate Cook
Nate Cook

Reputation: 93276

You have to declare your ThumbnailTableViewCellDelegate protocol as @objc:

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

This is because @IBOutlet declares the variable as weak, which only works with objects. I'm not sure why you can't just say the protocol conforms to AnyObject, perhaps that's a Swift bug.

Upvotes: 38

Steve Waddicor
Steve Waddicor

Reputation: 2217

IBOutlets are to indicate a pointer to an object stored in a nib (or storyboard) file. A protocol is not an object, therefore you can't have one in a nib file. Make the type of the IBOutlet var to be the type of the actual object you have in the nib.

Upvotes: -2

Related Questions