我知道,不建议对UIColor
进行子类化。苹果说
大多数开发人员不需要对 UIColor 进行子类化
但我愿意。更多关于为什么可以从我昨天发布的另一个问题中找到。 那个特定的问题解决了,但我遇到了另一个问题。
假设我有这个自定义颜色类:
class MyColor:UIColor{
convenience init(test:String){
self.init(red: 0, green: 0, blue: 0, alpha: 1)
}
}
//Then do this anywhere:
let myColor = MyColor(test: "test")
let temp:Any? = myColor
let c = temp as! MyColor
这会崩溃。它崩溃是因为它无法将temp
转换为MyColor
:
无法将类型"UIDeviceRGBColor"(0x..( 的值转换为"MyColor"(0x..(
myColor
是MyColor
的一个实例。这个相同的实例存储在Any?
类型的变量中,然后转换回MyColor
。但不能。
不过,如果我把它投UIColor
一切正常。但是在我的情况下我不能这样做(在上一个问题中解释过(。
为什么这不起作用?
问题是UIColor
是作为所谓的类集群实现的。这是一种类工厂,但工厂在引擎盖下隐含地工作。 在您的示例中,如果您打算创建一个MyColor
实例,则内部发生的情况如下:
MyColor.init
调用超类的初始值设定项- 然后,超类委托给内部类工厂,并将具体实现从
MyColor
更改为足以满足参数的内容,在您的情况下UIDeviceRGBColor
。 - 这意味着,
UIColor.init
确实返回了与您打算创建的实例不同的实例。这是UIColor
的一个子类,但不再是MyColor
。
在目标 C 中,您可以更轻松地跟踪此行为:
UIColor *color = [UIColor alloc];
NSLog(@"Address after alloc: %p - class: %@", color, [color class]);
color = [color initWithRed:1.0, green:1.0, blue:1.0, alpha:1.0];
NSLog(@"Address after init: %p - class: %@", color, [color class]);
在调用发起器后,您应该获得不同的地址和类。
UIColor 是一个类集群,在类别中使用关联引用来 添加属性!UIColor 上的所有自定义初始化方法都返回 UIColor* 不是 ID,因此您不能轻易地对 UIColor 进行子类化,也不应该 你试试。
您可以在下面遵循两个建议:
1-扩展
extension UIColor { convenience init(test:String){ self.init(red: 0, green: 0, blue: 0, alpha: 1) } } let myColor = UIColor(test: "test")
2- 组成
class MyColor { private(set) var color: UIColor init(test:String) { color = UIColor(red: 0, green: 0, blue: 0, alpha: 1) } } let myColor = MyColor(test: "test") let temp:Any? = myColor let c = temp as! MyColor