【问题标题】:Overriding "text" in UILabel does not work in iOS 6在 UILabel 中覆盖“文本”在 iOS 6 中不起作用
【发布时间】:2013-01-10 12:49:58
【问题描述】:

我的类“TypographicNumberLabel”是 UILabel 的子类。此类覆盖 UILabel 的“文本”设置器和获取器,目的是在表格中生成漂亮呈现的数字。例如,它可以为右对齐、一元加号、附加单元等添加一些额外的空白。

我的问题是这个类在 iOS 5.1 之前工作得非常好,但在 iOS 6 中,它已经停止工作:它现在完全按照标准 UILabel 呈现(但是当从代码访问它的属性时,它们仍然是给出正确的结果)。 由于这个类用于大量遗留代码,我真的很想修复我的原始代码,而不是使用全新的方法重写它。所以,请集中回答解释如何在 iOS 6 中为 UILabel 覆盖“-text”和“-setText:”。

这是我的代码(简化版):

@interface TypographicNumberLabel : UILabel {

        NSString *numberText;
    }

    // PROPERTIES

    // "text"            will be used to set and retrieve the number string in its original version.
    //                   integerValue, doubleValue, etc. will work as expected on the string.
    // The property "text" is declared in UILabel, but overridden here!

    // "typographicText" will be used to retrieve the string exactly as it is rendered in the view.
    //                   integerValue, doubleValue, etc. WILL NOT WORK on this string.
    @property (nonatomic, readonly) NSString* typographicText;

    @end

@implementation TypographicNumberLabel

- (void) renderTypographicText
{
    NSString *renderedString = nil;

    if (numberText) 
    {
        // Simplified example!
        // (Actual code is much longer.)

            NSString *fillCharacter = @"\u2007"; // = "Figure space" character

        renderedString = [fillCharacter stringByAppendingString: numberText];
    }

    // Save the typographic version of the string in the "text" property of the superclass (UILabel)
    // (Can be retreived by the user through the "typographicText" property.)

    super.text = renderedString;
}

#pragma mark - Overridden UILabel accessor methods

- (NSString *) text
{
    return numberText;
}


- (void) setText:(NSString *) newText
{
    if (numberText != newText)
    {
        NSString *oldText = numberText;
        numberText = [newText copy];
        [oldText release];
    }

    [self renderTypographicText];
}


#pragma mark - TypographicNumberLabel accessor methods

- (NSString *) typographicText
{
    return super.text;
}

@end

使用示例(aLabel从.xib文件加载):

@property(nonatomic, retain) IBOutlet TypographicNumberLabel *aLabel;

self.aLabel.text = @"12";
int interpretedNumber = [self.aLabel.text intValue];

这种类型的代码在 iOS 5.1 和 iOS 6 中都可以正常工作,但是在 iOS 6 中屏幕上的渲染是错误的!在那里,TypographicNumberLabel 就像 UILabel 一样工作。不会添加“图形空间”字符。

【问题讨论】:

    标签: ios ios6 uilabel


    【解决方案1】:

    问题出在

    - (NSString *) text
    {
        return numberText;
    }
    

    可以看到内部调用了方法([self text]),所以最好返回要显示的文本,否则很容易破坏内部控制逻辑:

    - (NSString *) text
    {
        return [super text];
    }
    

    【讨论】:

    • 非常感谢!我错误地认为 super.text 是从内部控制逻辑调用的,因此我对 text 的重新定义无关紧要,但现在我意识到这是错误的!我也明白我将来应该避免这种黑客行为。我给你一个赞成票!然而,即使这个答案解释了我的错误,它并没有完全解决我的问题,因为它破坏了与我的遗留代码的兼容性。我的代码依赖于 text 返回未格式化的字符串,而不是印刷字符串。
    【解决方案2】:

    提交问题后,我自己找到了解决方案。也许不是明确的解决方案,但至少是一个有用的解决方法。显然,在 iOS 6 中引入 attributedText 时,UILabel 的渲染逻辑发生了变化。我发现设置 attributedText 属性而不是 super.text会工作的。

    更具体地说: renderTypographicText

    中的以下行
        super.text = renderedString;
    

    应该替换为

        if (renderedString && [UILabel instancesRespondToSelector: @selector(setAttributedText:)])
        super.attributedText = [[[NSAttributedString alloc] initWithString: renderedString] autorelease];
    else
        super.text = renderedString;
    

    然后渲染又可以正常工作了!

    我承认,这有点“骇人听闻”,但它使我免于重写大量遗留代码。

    【讨论】:

    • 有趣的解决方案,我仍然计划重构:label.attributedText 将返回与label.text 相对的印刷文本
    • 好的。只是为了澄清一下:我的“TypographicNumberLabel”除了 NSAttributedString 还做了一些其他的事情,例如大量插入数千个分隔符并附加单位,因此它们不可互换。但我同意我可能应该在未来的设计中寻求另一种解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-07
    • 2015-05-25
    • 2014-04-14
    • 2018-02-13
    • 2020-01-14
    • 2017-12-04
    相关资源
    最近更新 更多