不支持从扩展覆盖非@objc声明

mic*_*ebo 8 ios swift

似乎无处不在,我开始遇到与我经常使用的两个扩展功能相关的数百个错误。

我尝试注释掉出现此错误之前的所有新代码。我还尝试清洁构建文件夹。我如何才能克服这篇文章标题中发现的错误?当我成功使用这些扩展包几个月后,为什么会随机出现?

extension UITableViewCell {

public func getSize(large: CGFloat, medium: CGFloat, small: CGFloat) -> CGFloat {
    var size = CGFloat()
    let screenHeight = Int(UIScreen.main.bounds.height)
    if screenHeight >= 800 {
        size = large
    } else if screenHeight >= 600 {
        size = medium
    } else {
        size = small
    }
    return size
}

public func formatPrice(_ price: Int) -> String {
    let lastDigit = price % 10
    var stringPrice = ""
    if lastDigit == 0 {
        stringPrice = "$\(Double(price) / 100)0"
    } else {
        stringPrice = "$\(Double(price) / 100)"
    }
    return stringPrice
}

}
Run Code Online (Sandbox Code Playgroud)

Jos*_*ann 18

如果将函数添加到扩展中的类中(即它们不在类定义中),则这些方法将迅速静态分派,因为编译器无法将方法添加到类的vtable中(即,vtable需要在编译时创建) ,但您可以稍后添加扩展名,例如在另一个模块中)。这就是为什么编译器抱怨您无法使用override这些方法(即它们是非虚拟的)的原因。

通过选择器表,目标C调度的工作方式有所不同,甚至可以在运行时对其进行修改。这就是为什么编译器说“使用” @objc并且足够确定是否可以使用它的原因。

例:

这不会编译,因为我们试图快速覆盖并动态分派静态分派的非虚函数

extension UITableViewCell {
    func a() {
        print("UITableViewCell")
    }
}

class B: UITableViewCell {
    override func a() {
        print("B")
    }
}

let b = B()
print(b.a())
Run Code Online (Sandbox Code Playgroud)

这有效并且打印“ B”,因为它使用objc选择器分派

import UIKit
import PlaygroundSupport

extension UITableViewCell {
    @objc func a() {
        print("UITableViewCell")
    }
}

class B: UITableViewCell {
    override func a() {
        print("B")
    }
}

let b = B()
print(b.a())
Run Code Online (Sandbox Code Playgroud)