我们想在遍历初始化器中使用self=???
的时候会报以下错误
Cannot assign to value: 'self' is immutable
举例:
我们想要加载本地库的UIImage的时候能够很方便的加载,那么想要给UIImage添加一个方法以便利使用
extension UIImage {
public convenience init?(named name: String, inCls class: AnyClass) {
guard let bundlePath = Bundle(for: `class`).paths(forResourcesOfType: "bundle", inDirectory: nil).first else {
return nil
}
self = UIImage(named: name, in: Bundle(path: bundlePath), compatibleWith: nil) as! Self
}
}
这样之后是编译不过的, 会在self = UIImage(named: name, in: B....
发生Cannot assign to value: 'self' is immutable
报错
解释
首先,请注意此限制仅适用于class
es,在struct
s 和enum
s中修改自身加上关键字mutating以后就能够了
这种对class
初始化器的限制是一个经常出现在这个站点上的痛点(例如)。在 Swift 论坛上有一个线程讨论这个问题,并且已经开始添加必要的语言特性来编译上面的示例代码,但这在 Swift 5.4 中还没有完成。从线程:
Swift 自己的标准库和 Foundation 覆盖层通过使类符合虚拟协议并在必要时使用协议扩展初始化器来实现此功能来绕过此缺失的功能。
解决方案
使用协议扩展初始化器解决
public protocol ResourceLoadProtocol {
}
extension UIImage : ResourceLoadProtocol {
}
extension ResourceLoadProtocol {
public init?(named name: String, inCls class: AnyClass) {
let resourceBundlePath = Bundle(for: `class`).paths(forResourcesOfType: "bundle", inDirectory: nil).first
self = UIImage(named: name, in: Bundle(path: resourceBundlePath!), compatibleWith: nil) as! Self
}
}
网友评论