0

My class "TypographicNumberLabel" is a subclass of UILabel. This class overrides the "text" setters and getters of UILabel with the purpose to produce nicely rendered numbers in a table. For instance, it can add some extra white space for right alignment, unary plus signs, append units, etc.

My problem is that this class has worked perfectly fine up to iOS 5.1, but in iOS 6, it has stopped working: It is now rendering exactly as the standard UILabel (but when its properties are accessed from code, they are still giving correct results). Since this class is used in a huge mass of legacy code, I would really like to repair my original code instead of rewriting it using completely new methods. So, please focus your answers on explaining how to override "-text" and "-setText:" for UILabel in iOS 6.

This is (a simplified version of) my code:

@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

Example of use (aLabel is loaded from .xib file):

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

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

This type of code works perfectly fine in both iOS 5.1 and in iOS 6, but the rendering on screen is wrong in iOS 6! There, TypographicNumberLabel works just like a UILabel. The "figure space" character will not be added.

4

2 回答 2

1

The issue is at

- (NSString *) text
{
    return numberText;
}

You can see the method ([self text]) is called internally, so it's better to return the text you want to be shown, otherwise you can easily ruin internal control logic:

- (NSString *) text
{
    return [super text];
}
于 2013-01-10T14:52:00.073 回答
0

After having submitted my question, I found a solution myself. Perhaps not the definite solution, but at least a useful workaround. Apparently, the rendering logic of UILabel has changed when attributedText was introduced in iOS 6. I found that setting the attributedText property instead of super.text will work.

To be more specific: The following line in renderTypographicText

    super.text = renderedString;

should be replaced with

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

then the rendering works fine again!

This is a bit "hackish", I admit, but it saved me from rewriting a huge amount of legacy code.

于 2013-01-10T15:05:05.213 回答