简体   繁体   中英

UILabel Attributed Text rendering incorrectly

I've been setting a UILabel using attributed text to get the font outlining that I want, and I change the UILabel's attributedText property fairly often. It seems that roughly 50% of the time it appears to render the new text OVER the old text without removing the old one. Right now my code looks like this:

// Attributes initialization
self.labelAttributes = [NSMutableDictionary dictionary];
[self.labelAttributes setObject: [UIFont fontWithName:@"Helvetica Neue" size:21] forKey: NSFontAttributeName];
[self.labelAttributes setObject: [UIColor whiteColor] forKey: NSForegroundColorAttributeName];
[self.labelAttributes setObject: [NSNumber numberWithFloat: -3.0] forKey: NSStrokeWidthAttributeName];
[self.labelAttributes setObject: [UIColor blackColor] forKey: NSStrokeColorAttributeName];

// Clear UILabel attributedString
self.userLabel.attributedText = [[NSAttributedString alloc] initWithString:@"" attributes:self.labelAttributes];
// Also attempted this with nil;


// Set UILabel to string, where self.userName and self.userAge are just regular strings. 
NSString *labelString = [NSString stringWithFormat:@"%@, %@", self.userName, self.userAge];
self.userLabel.attributedText = [[NSAttributedString alloc] initWithString:labelString attributes:self.labelAttributes];

When it works, it looks like this:

在此处输入图片说明

When it doesn't work, it looks like this:

在此处输入图片说明

This appears to be the last user's name, plus the current user's name overlayed on top of each other.

I can't figure out a good way to guarantee the label is cleared, and am not sure how to debug it. (I've tried using visual debugging in XCode 6, but it still thinks it's just one label, with the new user's text as the text attribute.)

It should already be correct by default but you could try it anyway:

self.userLabel.clearsContextBeforeDrawing = YES;
self.userLabel.contentMode = UIViewContentModeRedraw;

Interesting. Don't really know why that isn't working. Your code seems fine. Only thing I can think of is that if this is a label in a table view cell and it being reset after it is offscreen and then on screen? Otherwise, no idea.

Here is another way of doing the same thing that works for me.

NSString *labelString = [NSString stringWithFormat:@"%@, %@", self.userName, self.userAge];
self.userLabel.text = labelString;
NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc]initWithAttributedString:self.userLabel.attributedText];
[attStr addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Helvetica Neue" size:21] range:NSMakeRange(0, self.userLabel.length)];
[attStr addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:NSMakeRange(0, self.userLabel.length)];
[attStr addAttribute:NSStrokeWidthAttributeName value:[NSNumber numberWithFloat:-3.0f] range:NSMakeRange(0, self.userLabel.length)];
[attStr addAttribute:NSStrokeColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, self.userLabel.length)];
//or 1 liner
//[attStr addAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont fontWithName:@"Helvetica Neue" size:21], NSFontAttributeName, [UIColor whiteColor], NSForegroundColorAttributeName, [NSNumber numberWithFloat:-3.0f], NSStrokeWidthAttributeName, [UIColor blackColor], NSStrokeColorAttributeName, nil] range:NSMakeRange(0, self.userLabel.length)];
[self.userLabel setAttributedText:attStr];

Also, I don't see why you just can't set the label to have those properties to begin with, (if they are not changing throughout the label). You could just do:

NSString *labelString = [NSString stringWithFormat:@"%@, %@", self.userName, self.userAge];
self.userLabel.text = labelString;
self.userLabel.font = [UIFont fontWithName:@"Helvetica Neue" size:21];
self.userLabel.textColor = [UIColor blackColor];
//Then set the stroke with one attribute

Hope this helps! Happy coding.

You can do it as followed:

self.userLabel.attributedText = [[NSAttributedString alloc] 
initWithString:@"string to both stroke and fill" 
attributes:@{
             NSStrokeWidthAttributeName: [NSNumber numberWithFloat:-3.0],
             NSStrokeColorAttributeName: [UIColor blackColor],
             NSForegroundColorAttributeName: [UIColor whiteColor]
             }
];

I think I've seen this happen before with UITableCell reuse and dynamic table cell heights, determined at run time. This happens when cells are being set to height 0, if I remember correctly.

If you're in the above scenario, try turning clipsToBounds to on on the UITableViewCell, or the topmost reused view. Turning on clipsToBounds causes the labels, etc. to not flow out of the view when the containing view's frame size or height has been set to zero.

I suspect that the problem is not related with the attributed text. I suspect that the problem is that you are adding a new UILabel in a reused UITableViewCell, instead of reuse the old UILabel.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM