2

我有一个名为 color 的具有 UIColor 属性的类,我想通过字符串设置此属性:

[label setValue:@"1.0 0.5 0.0 1.0" forKey:@"color"];

我知道我需要将字符串转换为 UIColor。我注意到 KVC 调用了一个名为“componentRGBA”的方法,这是我要执行转换的地方。所以我在 NSString 上添加了一个分类方法:

-(UIColor*) componentRGBA
{
    CIColor* ciColor = [CIColor colorWithString:self];
    UIColor* uiColor = [UIColor colorWithCIColor:ciColor];
    return uiColor;
}

该方法被调用。但是,self它似乎不是一个有效的 NSString 对象,因为对 colorWithString: 的调用会因 EXC_BAD_ACCESS 而崩溃,每次发送selfNSObject 消息(类、描述等)的尝试也是如此。

我怀疑 componentRGBA 的方法签名不正确,因此 self 实际上不是字符串对象。虽然我无法通过谷歌搜索此方法找到任何参考。

如何正确实现componentRGBA,以便在通过 KVC 将 UIColor 属性设置为 NSString* 值时自动执行颜色转换?

更新:

有趣的是,当我在 componentRGBA 方法中执行此操作时:

CFShowStr((__bridge CFStringRef)self);

我收到消息:

这是一个 NSString,而不是 CFString

所以它应该是一个 NSString* 但我不能在不崩溃的情况下调用它的任何方法。

这个简单的测试例如崩溃:

NSLog(@"self = %@", [self description]);

崩溃发生在 objc_msgSend 中,code=1 和 address=0xffffffff(地址不时变化)。

此外,当我不实施时componentRGBA,KVC 会失败并显示以下消息:

-[__NSCFConstantString componentRGBA]: unrecognized selector sent to instance 0xc48f4
4

1 回答 1

2

这可能只是学术兴趣,因为您可能不想依赖未记录的方法,但以下实现似乎有效:

// This structure is returned by the (undocumened) componentRGBA
// method of UIColor. The elements are "float", even on 64-bit,
// so we cannot use CGFloat here.
struct rgba {
    float r, g, b, a;
};

@interface UIColor (ComponentRGBA)
-(struct rgba) componentRGBA;
@end

@interface NSString (ComponentRGBA)
-(struct rgba) componentRGBA;
@end

@implementation NSString (ComponentRGBA)
-(struct rgba) componentRGBA
{
    CIColor* ciColor = [CIColor colorWithString:self];
    UIColor* uiColor = [UIColor colorWithCIColor:ciColor];
    return [uiColor componentRGBA];
}
@end

我在您(现已删除)问题 KVC 的示例项目的帮助下弄清楚了这一点:设置颜色属性时,'componentRGBA' 方法做了什么?. 关键点是(通过检查堆栈回溯可以看出)该componentRGBA方法被调用 via objc_msgSend_stret(),这意味着它返回 astruct而不是 some id

于 2014-01-17T20:34:44.960 回答