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



我想在IB中连接一个自定义swift委托,该委托是在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?
    ^~~~~~~~~

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

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

这是因为@IBOutlet将变量声明为weak,它只对对象起作用。我不知道为什么你不能说协议符合AnyObject,也许这是一个Swift的错误。

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

  1. 将委托声明为AnyObject - @IBOutlet var delegate:AnyObject!
  2. 在Interface Builder中连接委托
  3. 将outlet的类型更改为你的协议,例如@IBOutlet var delegate:MyDelegate

不理想,但可以这样做:

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

必须确保你的objectTypeSomeProtocol一致,否则事情会爆炸

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

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

2023…

您只需在协议定义之前添加@objc

不需要在视图控制器中做任何修改

的例子:

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

然后在视图控制器中。

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

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

iboutlet是指向存储在nib(或storyboard)文件中的对象的指针。协议不是对象,因此你不能在nib文件中拥有一个。使IBOutlet变量的类型成为nib中实际对象的类型。