swift - 用 '@objc' 属性覆盖扩展方法背后的机制是什么?

标签 swift

有点 Nerd 的问题。我不清楚究竟是什么让这段代码起作用:

class Shape { }

extension Shape {
    @objc func redraw() {
        print("from ext")
    }
}

class Circle: Shape { }

class Line: Shape {
    override func redraw() { // Compiler error: Declarations from extensions cannot be overridden yet
        print("from subclass")
    }
}

let line = Line()
let shape:Shape = line
let circle = Circle()

line.redraw() //from subclass
circle.redraw() //from ext
shape.redraw() //from subclass

如果我在扩展中省略 @objc 关键字,代码将不会编译 - 这是预期的行为,因为扩展中的方法使用静态方法分派(dispatch) -> 不能被覆盖。 但是为什么添加 @objc 可以让它工作呢?根据文档和大多数文章,@objc 所做的只是让 Objective-c 运行时可见。要更改方法分派(dispatch)类型,有一个特殊的关键字 - dynamic。不过这里好像没必要!

帮我弄清楚,为什么添加 @objc(并省略 dynamic)使这些事情成为可能。

最佳答案

Extensions ,

as the name already says, are supposed to extend/add/include methods to an existing implementation, making them one of the most beautiful things about Objective-C, and now Swift, since you can add code to a class or framework you do not own. Therefore, it makes sense that you’re not supposed to “replace” code in extensions, conceptually speaking.

这就是编译器在您尝试这样做时会报错的原因。

另请查看此 answer .

然而这似乎也是一个支持问题,因为 swift 编译器只是抛出这个错误:

overriding non-@objc declarations from extensions is not supported.

据苹果称,

Extensions can add new functionality to a type, but they cannot override existing functionality.

但事实并非如此,因为我们是从扩展中覆盖而不是相反, 这将我们带回到 extension 的声明。

Extensions add new functionality to an existing class, structure, enumeration, or protocol type. This includes the ability to extend types for which you do not have access to the original source code (known as retroactive modeling). Extensions are similar to categories in Objective-C. (Unlike Objective-C categories, Swift extensions do not have names.) Here.

回到遗留主题 swift 编译器 vs Objc 编译器,

动态调度与静态调度

苹果没有官方文档说明为什么 swift 编译器不支持它,或者他们是否有任何 future 的计划来解决这个问题或将其视为一个问题。

However, there’s no such thing as Swift dynamic dispatch; we only have the Objective-C runtime’s dynamic dispatch. That means you can’t have just dynamic and you must write @objc dynamic. So this is effectively the same situation as before, just made explicit.

这是一个很棒的 article深入探讨这个话题。

关于swift - 用 '@objc' 属性覆盖扩展方法背后的机制是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54852486/

相关文章:

swift - 将数据从 Annotation 传递到下一个 VC

swift - 带有动画的文本字段四边形边框

swift - 如何使 Onboarding 与 iOS13 中的 Scene Delegate 配合使用?

ios - 使用 Objective-C/Swift 单例模型,为什么我们要创建一个共享实例而不只是使用类方法?

ios - CAShapeLayer。直线穿过点吗?

ios - 在 iOS 11 中,取消模态呈现的导航 Controller 会导致视觉重复

swift - 从核心数据中获取实体属性总和时出错

swift - SwiftUI 中的关联枚举状态

ios - 预定的 NSNotification(而不是 UILocalNotification)... Swift 解决方案?

ios - 动态 UIViewCell 垂直单元格滚动与水平 UICollectionViewFlowLayout