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

时间:2014-07-03 19:04:40

标签: ios interface-builder swift

我想在IB中连接一个自定义快速代表。委托是一个在swift中实现某个协议的对象。

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

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

不幸的是,编译器抱怨:

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

6 个答案:

答案 0 :(得分:31)

您必须将ThumbnailTableViewCellDelegate协议声明为@objc

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

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

答案 1 :(得分:14)

您可以使用此解决方法将IB中自己的协议连接起来。这是Xcode的一个已知问题,所以有一天可能会解决。在那之前:

  1. 将委托声明为AnyObject - @IBOutlet var delegate:AnyObject!
  2. 在Interface Builder中连接代理
  3. 将插座的类型更改为您的协议,例如@IBOutlet var delegate:MyDelegate
  4. 这适合我。

答案 2 :(得分:1)

不理想,但选择是做这样的事情:

@IBOutlet var objectType: NSObject!

private var conformingObject: SomeProtocol {
  return objectType as SomeProtocol
}

确保您的objectType符合SomeProtocol或事情会爆炸

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

使您的协议如下:

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

在你的类中声明它,例如:

@IBOutlet weak open var dataSource: AnyObject?

当你使用它时,检查它是否符合协议并且选项存在 - 如下所示:

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

答案 5 :(得分:-1)

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