在 UILabel 中覆盖“文本”在 iOS 6 中不起作用
Posted
技术标签:
【中文标题】在 UILabel 中覆盖“文本”在 iOS 6 中不起作用【英文标题】:Overriding "text" in UILabel does not work in 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 一样工作。不会添加“图形空间”字符。
【问题讨论】:
【参考方案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 还做了一些其他的事情,例如大量插入数千个分隔符并附加单位,因此它们不可互换。但我同意我可能应该在未来的设计中寻求另一种解决方案。以上是关于在 UILabel 中覆盖“文本”在 iOS 6 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章
根据文本动态获取UILabel的高度为iOS 7.0和iOS 6.1返回不同的值
Objective C - CAGradientLayer 覆盖 UILabel 中的文本?