Swift 4.1继承UIImage报错:不支持重写扩展中的非@objc声明
嘿,我来帮你搞定这个Swift 4.1的报错!咱们先搞清楚问题出在哪,再一步步解决。
报错原因
你遇到的Overriding non-@objc declarations from extensions is not supported错误,核心原因是:init(imageLiteralResourceName:)这个初始化方法是定义在UIImage的extension扩展里的,而且没有标记@objc。Swift 4.1开始严格限制了这种场景——子类不能重写来自extension且未标记@objc的方法,因为扩展的设计初衷是给类添加额外功能,不是用来提供可重写的接口的。
另外,你还给这个初始化方法加了required修饰符,这也是多余的:UIImage本身并没有把这个方法声明为必须实现的,所以子类完全不需要强制实现它。
解决方案
根据你的需求,有两种处理方式:
方案一:移除不必要的重写(推荐)
如果你的子类不需要专门处理image literal语法,直接删掉这个init(imageLiteralResourceName:)的实现就好!而且还要注意,你的自定义初始化方法init(bar: String)必须调用父类的指定初始化方法,否则编译器也会报错。
修改后的代码如下:
class Foo: UIImage { init(bar: String) { // 根据你的需求调用合适的父类初始化方法,这里举个例子 super.init(named: bar)! // 如果你不需要默认图片,也可以根据业务逻辑选择其他父类初始化方法,比如super.init(cgImage: ...) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
这样既解决了报错,也符合Swift的初始化规则。如果之后用到image literal,系统会自动调用UIImage父类的init(imageLiteralResourceName:)实现,完全不影响使用。
方案二:如果需要自定义imageLiteral处理
如果你确实需要在子类中处理image literal的逻辑,不要直接重写这个方法——可以通过自定义一个新的初始化方法,或者利用其他方式拦截。比如:
class Foo: UIImage { init(bar: String) { super.init(named: bar)! } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } // 自定义一个处理imageLiteral的方法,而不是重写父类的扩展方法 convenience init(customImageLiteral name: String) { self.init(bar: name) // 在这里添加你的自定义逻辑,比如图片预处理、日志记录等 } }
之后如果需要使用自定义的imageLiteral处理,直接调用这个自定义方法即可,避开重写扩展方法的限制。
内容的提问来源于stack exchange,提问作者Daniel Nilsson

