【问题标题】:Can't subclass DispatchGroup - "only visible via the Objective-C runtime"?不能继承 DispatchGroup - “仅通过 Objective-C 运行时可见”?
【发布时间】:2016-12-18 16:49:16
【问题描述】:

不能继承DispatchGroup,怎么办?

注意:

iOS 10+ 终于修复了这个问题

例如,携带一个有状态的包和一个组,

class PushDispatchGroup: DispatchGroup {
    var sentIds: [(tableName: String, rowId: String)] = []
}

感谢 shallowThought 指出这在 iOS10 中已修复。

【问题讨论】:

  • 你为什么要继承DispatchGroup?也许你的问题应该是关于你想要达到的目标。
  • 您的代码在这里编译得很好。由于error: 'DispatchGroupPlus' cannot be constructed because it has no accessible initializers,我无法创建实例。
  • @JoeBlow 这并不意味着你应该继承它。编写,不要继承。
  • @JoeBlow 这一点也不差。如果一个人来问“我怎样才能用锤子把螺丝钉进去?”,回答“改用螺丝刀”是一个完全有效的答案。为正确的工作使用正确的工具。
  • 它在 Xcode 10.2 上对我不起作用,我认为它在 iOS 10+ 中没有修复

标签: swift swift3 objective-c-runtime


【解决方案1】:

如何从“仅通过 Objective-C 运行时可见”的类继承?

你没有。

这并没有像您想象的那样包裹在适当的“对象”上。它包裹在 dispatch_group 周围,这是一个 C 结构。这个类不是为子类而设计的,也不能以正常的方式桥接到 ObjC,所以你也不能在那里子类。

直接桥接到低级 C 类型的“对象”通常具有非常不寻常的结构,系统的某些部分被硬编码以知道如何处理(这种情况一直发生在像NSStringCFString)。在许多情况下,通过仔细选择结构,这些类型被设计为在内存布局中相同(我没有挑选出DispatchGroup,但它看起来像是来自该组的一个)。如果是这样,您将无法添加任何存储,因为这样内存布局会有所不同,并且您会破坏桥接。

正如各种评论者所说,您也不应该这样做,这就是为什么如何这样做没有简单的答案。没有明确设计用于子类化的类在 Swift 中故意难以或不可能子类化(这经常出现在比DispatchGroup 更简单的类型,答案是相同的:这是故意的;不要这样做)。

【讨论】:

  • “它包裹着一个 dispatch_group,它是一个 C 结构”啊,太棒了,谢谢。
  • 我只是想知道@RobNapier,怎么知道(在这种情况下,比如说)DispatchGroup 实际上是一个 C 结构包装器? (当我点击“定义”时,我不够聪明,无法从中理解它是什么。)
  • 首先,通过知道dispatch_group 存在,它是一个结构,并且它被桥接到ARC(我之前研究过它是如何工作的)。 DispatchGroupOS_object,这意味着它是 libSystem“假”对象之一。有关它的一些评论,请参阅os/object.h。您还将看到为什么这可能会编译某些地方而不是其他地方(例如,他们在 10.12 中进行了更改)。但即使它编译了,也会非常危险(这就是为什么我确定他们添加了错误)。
  • 如果您对这类内容感兴趣,那么您肯定想阅读fish 所写的所有内容。具体从这里开始:ridiculousfish.com/blog/posts/bridge.html
  • "Open" 刚刚添加到 Swift 3 中。他们没有审核每个 Cocoa 类来决定应该打开哪个类,因此 "open" 是 Cocoa 导入器的默认设置。如果它是为子类化而设计的,那么文档中几乎总是会有“子类化注释”来解释如何。一个类可以任意子类化是非常罕见的(这是子类化的一个主要问题,也是避免它的一个原因:子类化几乎总是需要接口中没有的特殊知识)。
猜你喜欢
  • 2016-07-19
  • 2019-06-22
  • 2012-03-10
  • 1970-01-01
  • 1970-01-01
  • 2013-06-16
  • 2012-06-17
  • 2013-09-26
  • 2011-05-10
相关资源
最近更新 更多