Changing UILabel text but keeping the rest of the attributes
Asked Answered
V

7

14

I have a UILabel in my ViewController created using storyboards. The font, size and color of the label's text, its alignment - all set in the storyboard. The label in the storyboard is connected to the outlet in my file called p_patientNameLbl.

Now I am trying to change the text of the label programatically, like this:

[self.p_patientNameLbl setText:@"Vasya"];

I could not see the new text, until I realized that the original label in the storyboard was white on black background, but apparently after I changed the label's text as above, all the font attributes have been reset and now it was a black text on black background, and therefore not seen. Once I set the color programmatically:

[self.p_patientNameLbl setTextColor:[UIColor whiteColor]];

I could see the new label, but all the rest of the font attributes and alignment were still wrong.

Is there a way to change only the text of the label without having then programmatically to set all the rest of the attributes? I would imagine there must be a way, since I don't want to be formatting my interface in the code!

Valletta answered 23/1, 2013 at 19:45 Comment(1)
setText: shouldn't change your UILabel's color. If you NSLog self.p_patientNameLbl.textColor before and after you setText:, what does the log tell you?Spout
E
10

This is happening because you're telling Interface builder to take a label that had pre-defined attributes set on its text and replace this attributed text with plain text. Instead of setText, or setTextColor you have to use setAttributedText and specify the attributes that you wish to pass to the attributed string.

Here's an example of how to apply an attributed string to your label programmatically. I'm not aware of any better way, but using this, you can make changes to the text or text color and as long as you set your other attributes along with them, all changes will be applied correctly.

[myLabel setAttributedText:[self myLabelAttributes:@"Some awesome text!"]];

....................

- (NSMutableAttributedString *)myLabelAttributes:(NSString *)input
{
    NSMutableAttributedString *labelAttributes = [[NSMutableAttributedString alloc] initWithString:input];

    [labelAttributes addAttribute:NSStrokeWidthAttributeName value:[NSNumber numberWithFloat:-5.0] range:NSMakeRange(0, labelAttributes.length)];
    [labelAttributes addAttribute:NSStrokeColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, labelAttributes.length)];
    [labelAttributes addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:NSMakeRange(0, labelAttributes.length)];

    return labelAttributes;
}
Ejaculatory answered 23/1, 2013 at 20:14 Comment(4)
Note: It looks like I jumped to the conclusion that you are using attributed text instead of plain text in Interface Builder. If you aren't please disregard this answer.Ejaculatory
Correct, I am using attributed text. Now that I know what the issue is, I even found another stackOverflow on exactly the same issue:#12706688. Amazing - something so simple needs to be made so difficult! Thanks!Valletta
@user1959008 Glad to help! If my answer helped you then please mark it correct by clicking the "check mark" next to my post!Ejaculatory
@Valletta - Keep in mind that attributed text, though it's been around for awhile in other contexts, has only become useable in labels in the ios 6. So there's not a lot of experience with it.Katha
M
18

This works for me:

- (void)setText:(NSString *)text withExistingAttributesInLabel:(UILabel *)label {

    // Check label has existing text
    if ([label.attributedText length]) {

        // Extract attributes
        NSDictionary *attributes = [(NSAttributedString *)label.attributedText attributesAtIndex:0 effectiveRange:NULL];

        // Set new text with extracted attributes
        label.attributedText = [[NSAttributedString alloc] initWithString:text attributes:attributes];

    }

}

...

[self setText:@"Some text" withExistingAttributesInLabel:self.aLabel];
Maecenas answered 16/6, 2013 at 19:12 Comment(0)
A
11

One line implementation in Swift:

label.attributedText = NSAttributedString(string: "text", attributes: label.attributedText!.attributesAtIndex(0, effectiveRange: nil))
Aldus answered 20/6, 2016 at 7:29 Comment(1)
two hours until I found what was the issue, and 5 min to solve it thank to you ;)Axes
E
10

This is happening because you're telling Interface builder to take a label that had pre-defined attributes set on its text and replace this attributed text with plain text. Instead of setText, or setTextColor you have to use setAttributedText and specify the attributes that you wish to pass to the attributed string.

Here's an example of how to apply an attributed string to your label programmatically. I'm not aware of any better way, but using this, you can make changes to the text or text color and as long as you set your other attributes along with them, all changes will be applied correctly.

[myLabel setAttributedText:[self myLabelAttributes:@"Some awesome text!"]];

....................

- (NSMutableAttributedString *)myLabelAttributes:(NSString *)input
{
    NSMutableAttributedString *labelAttributes = [[NSMutableAttributedString alloc] initWithString:input];

    [labelAttributes addAttribute:NSStrokeWidthAttributeName value:[NSNumber numberWithFloat:-5.0] range:NSMakeRange(0, labelAttributes.length)];
    [labelAttributes addAttribute:NSStrokeColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, labelAttributes.length)];
    [labelAttributes addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:NSMakeRange(0, labelAttributes.length)];

    return labelAttributes;
}
Ejaculatory answered 23/1, 2013 at 20:14 Comment(4)
Note: It looks like I jumped to the conclusion that you are using attributed text instead of plain text in Interface Builder. If you aren't please disregard this answer.Ejaculatory
Correct, I am using attributed text. Now that I know what the issue is, I even found another stackOverflow on exactly the same issue:#12706688. Amazing - something so simple needs to be made so difficult! Thanks!Valletta
@user1959008 Glad to help! If my answer helped you then please mark it correct by clicking the "check mark" next to my post!Ejaculatory
@Valletta - Keep in mind that attributed text, though it's been around for awhile in other contexts, has only become useable in labels in the ios 6. So there's not a lot of experience with it.Katha
J
3

Swift 4

label.attributedText = NSAttributedString(string: "new label text", attributes: label.attributedText!.attributes(at: 0, effectiveRange: nil))

(a few minors changes from Bartłomiej Semańczyk answer)

Jacquelinejacquelyn answered 3/6, 2019 at 5:17 Comment(0)
T
1

0x7fffffff, thanks for your tip, that worked for me. In iOS6 some other advices here did not work eg. extracting the attributes and reapplying them.

In my case I was losing quite a few useful attributes, including the font, so here's my solution:

- (NSMutableAttributedString *)SetLabelAttributes:(NSString *)input col:(UIColor *)col size:(Size)size {

NSMutableAttributedString *labelAttributes = [[NSMutableAttributedString alloc] initWithString:input];

UIFont *font=[UIFont fontWithName:@"Helvetica Neue" size:size];

NSMutableParagraphStyle* style = [NSMutableParagraphStyle new];
style.alignment = NSTextAlignmentCenter;

[labelAttributes addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, labelAttributes.length)];
[labelAttributes addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, labelAttributes.length)];
[labelAttributes addAttribute:NSForegroundColorAttributeName value:col range:NSMakeRange(0, labelAttributes.length)];

return labelAttributes;
}

then apply it to the UILabel like this:

[self.myLabel setAttributedText:[self CurrentSetLabelAttributes:[NSString stringWithFormat:@"%d", myClass.text] col:[UIColor redColor]  size:50.0f]];
Tristantristas answered 20/6, 2013 at 13:6 Comment(0)
J
-1

I have done this many times for multiple apps. I always make my labels and text in Storyboard, changing their font size, color display, alpha value etc in editor. But afterwards if I need to change the text, which I have done a multiple times, all I do is this.

p_patientNameLbl.textColor = [UIColor redColor];
p_patientNameLbl.text = @"My Sample Text";

thats it. all the other default properties are kept. Unless I missed something in your question?

Jd answered 23/1, 2013 at 20:11 Comment(6)
Well, the size of the font, the alignment - they are all not the same after changing the text. So, I'd have to set those as well. But the issue is that really one is not supposed to worry about the look of the app in the code! If tomorrow I decide to change the look of my app and switch to a white background etc - which is done in storyboard - why would I need to go and change the code as well?Valletta
That is what I am saying that there is something wrong with your project or code. I also define my font size and alignment in stroyboard and I can change text color and font through code with NO impact to any other label attributes that I had defined through storyboarding for that label.Jd
@user1959008 Check your UILabel's color with NSLog(@"%@", self.p_patientNameLbl.textColor) before and after you setText. Does it change?Spout
Yes, the issue is that the storyboard uses an attributed text and this gets lost - which honestly looks more like a bug (or an oversight) than a feature to me.Valletta
NOTE: to anyone else - this problem is only with iOS 6.0 - iOS 5.0 works fine as I had suggestedJd
This answer is not using attributed strings and is probably a mistake.Consentient
H
-1

Instead of storing the old attributes and creating a new NSAttributedString with the changed text and stored attributes, a relatively easier way will be:

NSMutableAttributedString *attStr = [label.attributedText mutableCopy];
NSMutableString *str = attStr.mutableString;
/* change str with new text */
label.attributedText = attStr;
Heinz answered 27/10, 2015 at 11:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.