NSMutableAttributedString UILabel is not retaining its attributes when selected - uitableview

I am having issues with retaining an attributed NSMutableString. I have a UITableView who's each UITableViewCell has an attributed text. Setting the attributed text is no problem, but upon selection, the UITableViewCell's attributes is lost. This is my code in cellForRowAtIndexPath that sets the attribute:
NSMutableAttributedString *changesStyleString_h = [[NSMutableAttributedString alloc] initWithString:#"Attributes change!" attributes:#{NSFontAttributeName: [UIFont boldSystemFontOfSize:20], NSForegroundColorAttributeName:[UIColor yellowColor]}];
[changesStyleString_h addAttributes:#{ NSUnderlineStyleAttributeName:#(1)} range:NSMakeRange(11, 6)];
cell.mainLabel.attributedText = changesStyleString
might i point out that mainLabel is also a UILabel, no customization there. Any help in the right direction would be greatly appreciated!

I found that I needed to set attributes on the ENTIRE string, or it would do funky things.
NSString* string = #"1 - some string"
NSMutableAttributedString* string = [[NSMutableAttributedString alloc] initWithString:string];
[string setAttributes:#{NSForegroundColorAttributeName: accent, NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue-Bold" size:13.f]} range:NSMakeRange(0, 1)];
This would cause weird behavior when highlighting the cell.
However, when I did this:
[string setAttributes:#{NSForegroundColorAttributeName: [UIColor blackColor]} range:NSMakeRange(1, [labelTwo length] - 1)];
Everything seemed to work as expected.
Hope that helps!

Related

WatchKit, AttributedString formatting not working

I am building my first WatchKit App and am having troubles with NSAttributedString formatting as it does not seem to work as I'd expect ;)
This is my code:
UIFont *textFont = [UIFont fontWithName:#"Menlo" size:30];
UIFont *hlFont = [UIFont fontWithName:#"Menlo-Bold" size:30];
NSMutableAttributedString *information = [[NSMutableAttributedString alloc]initWithString:#"ADDED AN ENTRY OF " attributes:#{NSFontAttributeName : textFont}];
NSString *amountString = [NSString stringWithFormat:#"%.2f",(-1)*handler.amount.floatValue];
NSNumber *underline = [NSNumber numberWithInt:NSUnderlineStyleSingle];
NSAttributedString *amount = [[NSAttributedString alloc]initWithString:amountString attributes:#{NSFontAttributeName : hlFont, NSUnderlineStyleAttributeName : underline }];
NSAttributedString *to = [[NSMutableAttributedString alloc]initWithString:#" TO " attributes:#{NSFontAttributeName : textFont}];
NSString *categoryString = handler.category;
NSAttributedString *category = [[NSAttributedString alloc]initWithString:categoryString attributes:#{NSFontAttributeName : hlFont, NSUnderlineStyleAttributeName : underline }];
[information appendAttributedString:amount];
[information appendAttributedString:to];
[information appendAttributedString:category];
[_informationLabel setAttributedText:information];
and this the result:
Expectation
10.00 and Stuff should be underlined and in boldface.
Is there something fundamentally different to how attributed strings work on the watch than on iOS? What am I missing?
read through this: https://developer.apple.com/library/ios/documentation/General/Conceptual/WatchKitProgrammingGuide/TextandLabels.html
Solved it, the problem were the fonts #"Menlo".
By using
UIFont *textFont = [UIFont systemFontOfSize:20];
UIFont *hlFont = [UIFont systemFontOfSize:20];
the formatting with underlines works fine.
I don't believe you can programmatically set a label to be bold, italic, underlined....this has to be done through the actual interface in the storyboard.
According to this link
The attributes you can configure are
text
text color
font
min scale
alignment
lines
a potential workaround is to incorporate multiple labels, and set the ones you need to the right format (bold, underlined)

Bold part of detailTextLabel in UITableViewCell

As users search journals, I want to display a portion of the journal and the search term bolded in the detailTextLabel in UITableViewCell.
So like, SEARCH "today"
1/19/2014
Bright and sunnday, today is going to be a ...
How do you bold that word today, but not the rest of it?
cell.detailTextLabel.text = note.content;
detailTextLabel has the method setAttributedText so you can make an attributedText which you can customize dramatically, and then you can set it.
NSMutableAttributedString * attributedText = [[NSMutableAttributedString alloc] initWithString:note.content];
NSRange boldedRange = NSMakeRange(0, 5);// NSRange range = [displayingContent rangeOfString:self.notesSearchBar.text options:NSCaseInsensitiveSearch];
[attributedText addAttribute: NSFontAttributeName value:[UIFont fontWithName:#"Helvetica-Bold" size:16.0] range:boldedRange];
[cell.detailTextLabel setAttributedText: attributedText];

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 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.
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.

Setting attributedText of UILabel causing issue with Lengthier content

In my project I want to add an attributed text in UILabel placed on the xib.
It's working perfectly, but if large text appears it shows some issues.
My current implementation:
- (void)viewDidLoad
{
[super viewDidLoad];
_demoLabel.numberOfLines = 0;
_demoLabel.lineBreakMode = NSLineBreakByWordWrapping;
_demoLabel.attributedText = [self demoNameWithFontSize:21 andColor:[UIColor redColor]];
}
- (NSMutableAttributedString *)demoNameWithFontSize:(CGFloat)fontSize andColor:(UIColor *)color
{
NSMutableAttributedString *attributedText = nil;
NSString *demoName = #"Blah blah blah";
UIFont *demoFont = [UIFont fontWithName:#"Zapfino" size:fontSize];
attributedText = [[NSMutableAttributedString alloc] initWithString:demoName];
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.lineBreakMode = NSLineBreakByWordWrapping;
[attributedText addAttribute:NSParagraphStyleAttributeName value:paragraph range:NSMakeRange(0, [demoName length])];
[attributedText addAttribute:NSFontAttributeName value:demoFont range:NSMakeRange(0, [demoName length])];
[attributedText addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, [demoName length])];
return attributedText;
}
Output:
Issue:
It is not displaying the whole text, even if I applied the NSMutableParagraphStyle.
How can I solve this ?
Alternative I found:
If I change
UIFont *demoFont = [UIFont fontWithName:#"Zapfino" size:fontSize];
to
UIFont *demoFont = [UIFont systemFontOfSize:fontSize];
It'll work and gives output like:
But the issue is I need to use custom font, can't use default font. Also cannot change the font size.
I checked UILabel class reference and googled, but couldn't find a solution. Please help me.
Is there anyway to span this text into multiple lines ?
You need to resize the UILabel to fit the text.
You can calculate the size with the boundingRectWithSize:options:context: NSAttributedString class method, which takes an attributed string and calculates the size within a set rect based on all the attributes of the string.

Change color and size portion of NSString with NSMutableAttributedString

Browsed through a few NSAttributedString examples but can't seem to get this working. I am trying to change the size and color of part of a NSMutableAttributedString.
I've tried a few variations of this:
NSMutableAttributedString *hintText = [[NSMutableAttributedString alloc] initWithString:#"This is red and huge and this is not"];
//Black and large
[hintText setAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"Futura-Medium" size:20.0f], NSForegroundColorAttributeName:[UIColor blackColor]} range:NSMakeRange(0, 11)];
//Rest of text -- just futura
[hintText setAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"Futura-Medium" size:16.0f]} range:NSMakeRange(12, ((hintText.length -1) - 12))];
This just changes the size of the text, not the color. Can someone point me in the right direction?
EDIT: I use this like so: myUILabel.attributedText = hintText;
When I'm trying to do something like this, I find it to be easier to build individual pieces (each of which is an NSAttributedString) and then "glue" them together with something like the following:
NSAttributedString *string1 = // Get the red and large string here
NSAttributedString *string2 = // Get the just futura string here
NSMutableAttributedString *hintText = [[NSMutableAttributedString alloc] init];
[hintText appendAttributedString:string1];
[hintText appendAttributedString:string2];
I find this makes it much easier to follow the logical flow and I've never found this way to have performance limitations that needed optimization.
Update:
FWIW, I got the following code to work as I believe the OP desires:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSMutableAttributedString *hintText = [[NSMutableAttributedString alloc] initWithString:#"This is red and huge and this is not"];
//Red and large
[hintText setAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"Futura-Medium" size:20.0f], NSForegroundColorAttributeName:[UIColor redColor]} range:NSMakeRange(0, 20)];
//Rest of text -- just futura
[hintText setAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"Futura-Medium" size:16.0f]} range:NSMakeRange(20, hintText.length - 20)];
[self.button setAttributedTitle:hintText forState:UIControlStateNormal];
}
Note that he was specifying [UIColor blackColor] and I updated that to [UIColor redColor]. Also, I updated the range calculations to include all of the characters in "This is red and huge".

Resources