Я пробовал это как метод в моем контроллере представления, но мне бы очень хотелось, чтобы он был в метке.

Я действительно хочу реализовать такую ​​категорию, как «UILabel+formattedText», которая позволит мне выполнить метод, который будет красиво форматировать текст в видимом отображении метки, но любой код, который просматривает label.text, просто видит неформатированную числовую строку. Я знаю, что это, наверное, очень просто. Дело в том, что я не могу найти синтаксис для этого. Как именно это будет работать?

Вот мой набросок метода внутри контроллера представления:

- (void)UpdateLabels{
    if(!formatter){//initialize formatter if there isn't one yet.
        formatter = [[NSNumberFormatter alloc] init];
        [formatter setNumberStyle:NSNumberFormatterDecimalStyle];
        [formatter setPositiveFormat:@",##0.##"]; 
        [formatter setNegativeFormat:@",##0.##"];
        [formatter setMaximumFractionDigits:15];
        [formatter setMaximumIntegerDigits:15];

    }
    NSRange eNotation =[rawDisplay rangeOfString: @"e"];//if there's an 'e' in the string, it's in eNotation.
    if ([rawDisplay isEqual:@"Error"]) {
        display.text=@"Error";
        backspaceButton.enabled = FALSE;
    }else if (eNotation.length!=0) {
        //if the number is in e-notation, then there's no special formatting necessary.
        display.text=rawDisplay;
        backspaceButton.enabled =FALSE;
    } else {
        backspaceButton.enabled =([rawDisplay isEqual:@"0"])? FALSE: TRUE; //disable backspace when display is "0"            
        //convert the display strings into NSNumbers because NSFormatters want NSNumbers
        // then convert the resulting numbers into pretty formatted strings and stick them onto the labels
        display.text=[NSString stringWithFormat:@"%@", [formatter stringFromNumber: [NSNumber numberWithDouble:[rawDisplay doubleValue]]]];           
    }
}

Поэтому я в основном хочу, чтобы по крайней мере функциональность рисования этикетки входила в этикетку. Кстати, этот код соответствует MVC? Это моя первая попытка.

Кроме того, пока я здесь, я могу также спросить: это переходит в нотацию e с относительно небольшим количеством цифр как двойное число. Но когда я пытаюсь изменить double на что-то другое, например longlong, я получаю очень странные результаты. Как я могу иметь большую точность и при этом выполнять все эти операции?


person Dave Kliman    schedule 03.07.2011    source источник


Ответы (1)


Я бы предложил написать подкласс UILabel. Поскольку все, что вы хотите сделать, это изменить способ отображения текста, вам просто нужно написать собственный метод drawTextInRect:. Он будет использовать формат значения из self.text и нарисует результирующую строку. Затем вам просто нужно изменить класс любой метки, которая должна быть отформатирована.

Пример:

@interface NumericLabel : UILabel {}
@end

@implementation NumericLabel
- (void)drawTextInRect:(CGRect)rect {
    static NSNumberFormatter *formatter;
    NSString *text = nil, *rawDisplay = self.text;

    if(!formatter){
        //initialize formatter if there isn't one yet.
    }
    NSRange eNotation =[rawDisplay rangeOfString: @"e"];//if there's an 'e' in the string, it's in eNotation.
    if ([rawDisplay isEqual:@"Error"]) {
        text = @"Error";
    }else if (eNotation.length!=0) {
        text = rawDisplay;
    } else {
        text=[formatter stringFromNumber: [NSNumber numberWithDouble:[rawDisplay doubleValue]]];           
    }

    [text drawInRect:rect withFont:self.font lineBreakMode:self.lineBreakMode alignment:self.textAlignment];
}
@end
person ughoavgfhw    schedule 03.07.2011
comment
когда я спросил, должен ли я сделать это на прошлой неделе, людям это, похоже, не понравилось... но да, это тоже неплохо... я только изучаю этот материал, и я рад, что приведенный выше код вообще работает . Я уверен, что это можно сделать намного лучше, но это дело будущего. можете ли вы привести пример в коде, показывающий, как это будет выглядеть? - person Dave Kliman; 03.07.2011
comment
@Dave Дэйв, я добавил пример кода. Я также изменил ответ, чтобы показать, что вы должны использовать drawTextInRect: вместо drawRect:. Обратите внимание, что в примере не включается/отключается backspace, поскольку представление не должно делать этого в MVC (и вы должны сделать это до отображения представления). - person ughoavgfhw; 03.07.2011
comment
Спасибо за это. Я думал, что понял это, но я думаю, что нет.. изменение на пользовательскую метку убило этот код: //Dynamic display resizing. self.numberOfLines=1; self.adjustsFontSizeToFitWidth=YES; self.minimumFontSize=15.0f; который в этой итерации я пытался вставить в метод инициализации пользовательской метки... нет? куда мне это положить? - person Dave Kliman; 03.07.2011
comment
Автоматическое изменение размера шрифта, вероятно, происходит в процедуре рисования. Поскольку вы делаете пользовательский рисунок, вам придется реализовать его самостоятельно. Посмотрите на sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode: для расчета размера шрифта, который следует использовать для рисования. - person ughoavgfhw; 06.07.2011
comment
кто-то правильно объяснил мне тот полезный факт, что иметь это в метке, которая может вызываться и перерисовываться гораздо больше раз, чем изменяется текст, - это огромный расход ресурсов... поэтому я поместил все это обратно в контроллер представления, где я предположим, что это принадлежит, и все хорошо, хех. Также другой большой ошибкой было то, что super не вызвали для рисования, так как он мог... - person Dave Kliman; 06.07.2011