8

比较或测试 NSAttributed 字符串的特定颜色属性的正确方法是什么?

例如,我想知道文本选择是否有红色文本。正如您在下面看到的,我尝试了几种方法,但它们都没有导致匹配。我看到屏幕上的文本变成红色,并且记录属性返回: UIDeviceRGBColorSpace 1 0 0 1

- (BOOL)isRedWithAttributes:(NSDictionary *)attributes
{
    BOOL isRedWithAttributes = NO;
    if (attributes != nil)
    {
// if ( [attributes objectForKey:NSForegroundColorAttributeName] == [UIColor redColor] )    
// if ( [attributes objectForKey:NSForegroundColorAttributeName] == @"UIDeviceRGBColorSpace 1 0 0 1" )

       if ( [attributes objectForKey:NSForegroundColorAttributeName] == [UIColor colorWithRed:1 green:0 blue:0 alpha:1] )
       {
            isRedWithAttributes = YES;
        }
        else
        {
            isRedWithAttributes = NO;
        }
    }
    return isRedWithAttributes;
}

这是我为测试传递属性的方式:

NSAttributedString *selectedString = [attributedString attributedSubstringFromRange:selectedRange];
        [selectedString enumerateAttributesInRange:NSMakeRange(0, [selectedString length]) 
options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
                              usingBlock:^(NSDictionary *attributes, NSRange range, BOOL *stop)
        {
            UIFont *fontFace = [attributes objectForKey:NSFontAttributeName];       
            BOOL isRedWithAttributes = [fontFace isRedWithAttributes:attributes];
            if (isRedWithAttributes)
            {
                NSLog(@"detected red. set selected");
                [self.redButton setSelected:YES];
            }
            else
            {
                NSLog(@"detected not red. do not set selected");
                [self.redButton setSelected:NO];
            }
}

我认为这并不重要,但为了完整起见,这是我将文本设置为红色的方式。

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.synopsisTextView.attributedText];
[attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:selectedRange];
self.synopsisTextView.attributedText = attributedString;
4

3 回答 3

9

Objective-C 是 C 的严格超集。Objective-C 对象存在于堆上并通过指针跟踪。这样做的最终结果是测试:

[attributes objectForKey:NSForegroundColorAttributeName] == 
[UIColor colorWithRed:1 green:0 blue:0 alpha:1]

测试身份而不是平等。也就是说,不是测试两个对象是否具有相同的值,而是测试它们是否是相同的物理对象,位于内存中的相同地址。C 不允许运算符重载,因此==运算符在 Objective-C 中的含义与在 C 中的含义完全相同。您正在比较两个指针。他们碰巧指向Objective-C对象既不存在也不存在。

你可能想要:

[[attributes objectForKey:NSForegroundColorAttributeName] isEqual:
    [UIColor colorWithRed:1 green:0 blue:0 alpha:1]]

这将允许UIColor对象应用它认为将建立平等的任何测试。

唯一可能的警告是,UIColor只有当它们相对于相同的颜色空间定义并且具有相同的系数时,才认为颜色是相等的。假设您总是在 RGBA 中定义所有不应该产生影响的颜色。

于 2012-12-07T02:04:01.263 回答
5

尝试在属性字典中测试NSForegroundColorAttributeName对象,而不是NSFontAttributeName像这样:

NSAttributedString *selectedString = [attributedString attributedSubstringFromRange:selectedRange];
[selectedString enumerateAttributesInRange:NSMakeRange(0, [selectedString length]) 
                                   options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired 
                                usingBlock:^(NSDictionary *attributes, NSRange range, BOOL *stop) {
    UIColor *fgColor = [attributes objectForKey:NSForegroundColorAttributeName];       
    if ([fgColor isEqual:[UIColor redColor]]) {
        NSLog(@"detected red. set selected");
        [self.redButton setSelected:YES];
    } else {
        NSLog(@"detected not red. do not set selected");
        [self.redButton setSelected:NO];
    }
}
于 2012-12-07T02:07:21.343 回答
0

您必须-isEqualToColor:为比较创建一个方法。UIColor 仅从 NSObject 继承一个-isEqual:,如果它们的哈希值相等,这将看到 UIColor 的两个实例相等。

这种方法相当容易构造,您只需获得独立于颜色空间的 RGB+A 值,并且如果所有这些值都相同,则颜色相等。

如果你很懒,你会使用CGColorEqualToColor,但如果一个是灰色(2 个组件)而另一个是 RGBA 颜色(4 个组件),则不会报告相等性。

这可能是 Apple 没有实施-isEqualToColor:方法的原因,因为如果组件的数量应该发挥作用,或者只是 RGB 值,意见会大相径庭。因此,我建议您找到自己的定义并相应地进行比较。

PS:您可能会发现 isEqual 在某些情况下有效,因为 UIColor 保留了一些标准颜色的缓存,例如,如果您请求红色,那么您将获得相同的实例。相同的实例意味着相同的散列,因此“相等”。但正如我之前所说的那样,依赖于实现并不是很好的风格。

于 2012-12-21T19:21:37.773 回答