我正在尝试创建一个带有附加属性的 UIImage 子类,但是当我创建一个方便的 init 时,我无法调用 UIImage 指定的 init init(名为 name: String),因为由于某种原因它不是继承的。
class myUIImage: UIImage {
var imageType$: String?
convenience init(imageName$ imageName$: String) {
self.init(...?)
self.imageType$ = // ...
}
}
有什么想法吗?
UIImage
不是为子类而设计的(你会注意到它的文档中缺少"子类化注释")。正如您所发现的,尝试对其进行子类化有许多棘手的小问题。这在与核心基础类密切相关的可可类中很常见(在这种情况下是UIImage
和CGImageRef
)。
一般来说,你应该用组合而不是继承来解决这个问题。创建一个包含image
和imageType
属性的新结构,然后使用它。
如果有更深层次的原因需要将类型附加到真正的UIImage
,这可以通过运行时技巧来完成(见objc_setAssociatedObject
),但这应该保留在无法组合的情况下。最常见的是当您将对象传递给某个 API 时,该 API 稍后会将其交还给您,并且您需要随之传递一些侧信道信息。我在处理UIAlertView
时经常使用它,但通常简单的构图更好。
named: 中存在"未继承"字符串: 初始值设定项声明:
public /*not inherited*/ init?(named name: String) // load from main bundle
我不确定"未继承"到底代表什么,但看起来它的真正性质是"方便初始化器",你不能在子类中使用它。至少它的行为是这样的。所以,我建议你走以下几条路:
class TheImage: UIImage {
var param: String! = nil
convenience init?(param: String) {
guard let image = UIImage(named: "TheImage") where nil != image.cgImage else {
return nil
}
self.init(cgImage: image.cgImage!)
self.param = param
}
}
另一方面,通常你真的不需要对UIImage进行子类化。在大多数情况下,创建一个包装类就足够了,而且更合适。
Subclassing UIImage有点时髦。但这是可以做到的
class PlaceHolderIcon: UIImage {
// any additional properties can go here
override init() {
let image = UIImage(named: "image-name")!
super.init(cgImage: image.cgImage!, scale: UIScreen.main.scale, orientation: .up)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
required convenience init(imageLiteralResourceName name: String) {
fatalError("init(imageLiteralResourceName:) has not been implemented")
}
}