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

Posted

技术标签:

【中文标题】swift 协议,IBOutlet 属性不能有非对象类型【英文标题】:swift protocol, IBOutlet property cannot have non-object type 【发布时间】:2014-07-03 19:04:39 【问题描述】:

我想在 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?
    ^~~~~~~~~

【问题讨论】:

@Andy 没关系 - 你是说它是一个符合该协议的对象。 【参考方案1】:

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

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

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

【讨论】:

感谢 Nate,这很有效!这是临时解决方法还是预期行为?在这种情况下@objc 的相关性是什么? 这个方法不再适用于我(使用 Xcode 6 的 GM 种子) 这可以编译,但我现在在连接故事板中的插座时遇到了问题 是的,在 xcode 6.2 上也是如此……有人解决了这个问题吗? 您可以使用下面 Morten J 的解决方法,或者在代码中手动设置委托,而不是在情节提要中。如果你还没有引用 ThumbnailTableViewCell,你必须先创建一个 outlet。【参考方案2】:

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

    将委托声明为 AnyObject - @IBOutlet var delegate:AnyObject! 在 Interface Builder 中连接委托 将出口的类型更改为您的协议,例如@IBOutlet var delegate:MyDelegate

这对我有用。

【讨论】:

是否有已知的雷达或发行说明记录了这一点?【参考方案3】:

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

@IBOutlet var objectType: NSObject!

private var conformingObject: SomeProtocol 
  return objectType as SomeProtocol

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

【讨论】:

【参考方案4】:

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

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

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

【讨论】:

以上是关于swift 协议,IBOutlet 属性不能有非对象类型的主要内容,如果未能解决你的问题,请参考以下文章

是否需要释放一个 IBOutlet 控件? (非弧)

为啥我不能在 Swift 中使用 let in 协议?

未加载 CollectionView 单元格的 UIImageView IBOutlet 属性

Swift、iboutlet 和自定义控件

如何使用 Swift 以编程方式分配 IBOutlet?

无法在 Swift 2 中将 TableView @IBOutlet 连接到 ViewController