swift协议,IBOutlet属性不能具有非对象类型

时间:2022-09-11 19:13:16

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

我想在IB中连接一个自定义的快速代表。委托是一个在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?
    ^~~~~~~~~

6 个解决方案

#1


29  

You have to declare your ThumbnailTableViewCellDelegate protocol as @objc:

您必须将ThumbnailTableViewCellDelegate协议声明为@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.

这是因为@IBOutlet将变量声明为弱,仅适用于对象。我不确定为什么你不能说协议符合AnyObject,也许这是一个Swift错误。

#2


14  

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:

您可以使用此变通方法在IB中连接自己的协议。这是Xcode的一个已知问题,所以有一天可能会解决。直到那时:

  1. Declare the delegate as an AnyObject - @IBOutlet var delegate:AnyObject!
  2. 将委托声明为AnyObject - @IBOutlet var delegate:AnyObject!
  3. Connect the delegate in Interface Builder
  4. 在Interface Builder中连接委托
  5. Change the outlet's type to your protocol, e.g. @IBOutlet var delegate:MyDelegate
  6. 将插座的类型更改为您的协议,例如@IBOutlet var delegate:MyDelegate

This works for me.

这对我有用。

#3


0  

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.

协议类型的变量可能不是对象,因为结构和枚举也可以符合协议。要确保协议只能由类符合,您可以使用@class_protocol声明协议。

#4


0  

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

必须确保你的objectType符合SomeProtocol,否则会爆炸

#5


0  

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:

IB需要AnyObject而不是您的特定协议才有意义。您想要连接的对象可能,但不一定符合协议,协议可能有选项 - 所以:

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))
}

#6


-1  

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.

IBOutlets用于指示存储在nib(或storyboard)文件中的对象的指针。协议不是对象,因此您不能在nib文件中拥有一个协议。使IBOutlet var的类型成为nib中实际对象的类型。

#1


29  

You have to declare your ThumbnailTableViewCellDelegate protocol as @objc:

您必须将ThumbnailTableViewCellDelegate协议声明为@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.

这是因为@IBOutlet将变量声明为弱,仅适用于对象。我不确定为什么你不能说协议符合AnyObject,也许这是一个Swift错误。

#2


14  

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:

您可以使用此变通方法在IB中连接自己的协议。这是Xcode的一个已知问题,所以有一天可能会解决。直到那时:

  1. Declare the delegate as an AnyObject - @IBOutlet var delegate:AnyObject!
  2. 将委托声明为AnyObject - @IBOutlet var delegate:AnyObject!
  3. Connect the delegate in Interface Builder
  4. 在Interface Builder中连接委托
  5. Change the outlet's type to your protocol, e.g. @IBOutlet var delegate:MyDelegate
  6. 将插座的类型更改为您的协议,例如@IBOutlet var delegate:MyDelegate

This works for me.

这对我有用。

#3


0  

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.

协议类型的变量可能不是对象,因为结构和枚举也可以符合协议。要确保协议只能由类符合,您可以使用@class_protocol声明协议。

#4


0  

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

必须确保你的objectType符合SomeProtocol,否则会爆炸

#5


0  

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:

IB需要AnyObject而不是您的特定协议才有意义。您想要连接的对象可能,但不一定符合协议,协议可能有选项 - 所以:

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))
}

#6


-1  

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.

IBOutlets用于指示存储在nib(或storyboard)文件中的对象的指针。协议不是对象,因此您不能在nib文件中拥有一个协议。使IBOutlet var的类型成为nib中实际对象的类型。