UIColor-subclass 在从 Any 转换时崩溃?



我知道,不建议对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..(

myColorMyColor的一个实例。这个相同的实例存储在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

最新更新