Why is my NSAttributed String losing its attributes when the view reappears? - ios

I am using UIAppearanceProxy in my app, like so:
UILabel *label = [UILabel appearance];
label.font = myAppFont;
label.textColor = myAppTextColor;
Sometimes, though, I want to override the default font to use glyphs from Awesome Font. I do that like this:
NSString *basePos = [NSString stringWithFormat:#"%d %#", (int)self.user.positives, kUpArrow];
NSMutableAttributedString *posString = [[NSMutableAttributedString alloc] initWithString:basePos];
[posString setAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"FontAwesome" size:18]} range:NSMakeRange([posString length] - 1, 1)];
[self.positivesLabel setAttributedText:posString];
This works great when the view is built and appears, but if I navigate to another page (I am using UIPageViewController) and back, my attributes are gone.
I've tried re-setting-up the attributes in:
viewWillAppear:
viewDidAppear:
viewWillLayoutSubviews
viewDidLayoutSubviews
...to no avail. When is this string getting reset to the default? And how can I override that?

A similar thing was happening in to me.
The reason that this was happening was because I had set the font property on the appearance proxy of UILabel, and for whatever reason that overtook the attributes of the attributed string when the view re-appeared.
I fixed this by setting the font property on the UILabel to nil before setting the attributedText. Note that setting the font to any font also fixed this issue; it does not necessarily need to be set to nil.

Related

IOS Objective C UILabel font size is keeping its storyboard setting

I am using objectiveC for an old project and I am setting the label font size programmatically like this :
UIFont *font = [self fontToFitHeight:NSLocalizedString(#"#61_NEW_FINAL", nil) font:self.rulesLabel.font size:self.rulesLabel.frame.size.height];
[self.rulesLabel setFont:font];
NSLog(#"after call : fontszie is : %lf",self.rulesLabel.font.pointSize);
I can include the helper function if needed, but it returns me what I want, which is a font with fontsize around 5, which i see printed.
But when running that my font size is definitely not 5, but instead whatever value I have in the Storyboard settings (in my case 16). Above code is called inside viewDidLoad.
What am I missing?
NSAttributedString can include one or more fonts, perhaps this is your issue. If you have set the text of the label to be an attributed string that contains a font or a color, changing the base font or color of the label will not make a difference. In order for it to work as expected, you can either remove any font formatting of your attributed string (that I assume that you set through IB) or recreate the string in code and add the proper font to it, like so:
NSString *text = NSLocalizedString(#"#61_NEW_FINAL", #"Don't leave this out");
UIFont *font = [self fontToFitHeight:text font:self.rulesLabel.font size:self.rulesLabel.frame.size.height];
NSMutableAttributedString *labelAttributes = [[NSMutableAttributedString alloc] initWithString:text];
[labelAttributes addAttribute:NSFontAttributeName
value:font
range:NSMakeRange(0, labelAttributes.length)];
At this point, changing the font of the label will make absolutely no difference to its apperance, since the entire text has a predefined font already.

Adding multiple lines to a UILabel that is updated by a UITextField

So i'm making an application where the user converts the data from a UITextField into a UILabel. However, when updating a large amount of text instead of overflowing into another line, it simply displays '...' when there are too many words. I've tried changing the number of lines in the UILabel, even changing it to '0' which should mean the text displayed should fit the words in the UITextField, but this isn't the case. The following code I have for the UITextField to the UILabel is:
- (IBAction)add:(id)sender {
NSString *input = text1.text;
label1.text = input;
NSString *Input = text2.text;
label2.text = Input;
I'm new to developing and I've checked documentation and have found nothing. I did notice someone saying I should use a UITextField, however this doesn't suit my needs as to what i require the UILabel to display.
Maybe try setting the lineBreakMode property of the UILabel to NSLineBreakByWordWrapping, as the default value for this property is actually NSLineBreakByTruncatingTail which could explain the '...' that you're experiencing when the label has too much text. Also make sure the adjustsFontSizeToFitWidth property is set to NO.
textLabel.adjustsFontSizeToFitWidth = NO; // this is default value
textLabel.lineBreakMode = NSLineBreakByWordWrapping;
textLabel.numberOfLines = 0;
Options for UITextView that you may have not seen
UITextView * _descriptionText = [UITextView new];
[_descriptionText setTextAlignment:NSTextAlignmentLeft];
[[_descriptionText textContainer] setMaximumNumberOfLines:11];
[[_descriptionText textContainer] setLineBreakMode:NSLineBreakByTruncatingTail];
Not sure if this helps, but combining this with Bamsworlds answer should do it

how to set a UITextView's text to be bolded and not clickable

I have the following HTML in a UITextView and would like to render it into a UITextView
is my body for the note
food item - more item stuff;`
Let me add: it's currently showing as blue and underlined and not clickable. I would like to make it bolded and not clickable. I have read the docs regarding linkTextAttributes but, not having used this, it is a bit beyond me and I don't really see any easy way to manipulate this. How would I just render the above link bolded and black (not blue) and maintain the non-clickable nature?
UPDATE (solution using UITextView's linkTextAttributes)
self.testTextView.editable = NO;
self.testTextView.selectable = YES;
self.testTextView.userInteractionEnabled = NO; // workaround to disable link - CAUTION: it also disables scrolling of UITextView content
self.testTextView.dataDetectorTypes = UIDataDetectorTypeLink;
self.testTextView.linkTextAttributes = #{NSFontAttributeName : [UIFont boldSystemFontOfSize:14.0f], // NOT WORKING !?
NSForegroundColorAttributeName : [UIColor redColor]};
...
self.testTextView.text = #"Lorem ipsum http://www.apple.com Lorem ipsum";
As you can see in comments, I wasn't able to set new font to linkTextAttributes, though the colour attribute was working as expected.
If you can get away with colour attribute or some other text attribute to style your URLs and you don't have to worry about disabled UITextView scrolling, then this may be your solution.
PREVIOUS (alternative solution)
If you're using Storyboard/xib then make sure you've deselected Detection -> Links for your UITextView. You can make your link bold by setting its container font to some bold typeface. If you want to support different text/font styles in one string object then you should really look for NSAttributedString or NSMutableAttributedString.
See: https://developer.apple.com/library/ios/documentation/cocoa/reference/foundation/classes/NSAttributedString_Class/Reference/Reference.html.
Example:
UIFont *linkFont = [UIFont fontWithName:#"SomeBoldTypeface" size:12];
NSString *link = #"food item - more item stuff";
NSMutableAttributedString *someString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:#"is my body for the note %#; let me ad", link]];
[someString addAttribute:NSFontAttributeName value:linkFont range:NSMakeRange(24, link.length)];
UITextView *textView = [[UITextView alloc] init];
textView.attributedText = someString;
...

UITextview typingAttributes not working

I have UITextView and I want to set it's line height to 50.0f so I'm using typingAttributes, but nothing works, my code goes like this in ViewDidAppear Method
UITextView *textView = [[UITextView alloc]initWithFrame:CGRectMake(0, 0, 300, 300)];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.minimumLineHeight = 50.0f;
paragraphStyle.lineHeightMultiple = 50.0f;
paragraphStyle.maximumLineHeight = 50.0f;
NSDictionary *textViewAttributeDic = [NSDictionary dictionaryWithObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
textView.typingAttributes = textViewAttributeDic;
text doesn't effected by setting typingAttributes,and I tried to changed the color and font using typingAttributesbut nothing works
i've read all stack answers and documentation
what i'm doing wrong :(
update:
i even tried
UITextView *textView = [[UITextView alloc]initWithFrame:CGRectMake(0, 0, 300, 300)];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.minimumLineHeight = 50.0f;
paragraphStyle.lineHeightMultiple = 50.0f;
paragraphStyle.maximumLineHeight = 50.0f;
NSDictionary *textViewAttributeDic = [NSDictionary dictionaryWithObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
textView.attributedText = [[NSAttributedString alloc] initWithString:#"" attributes:textViewAttributeDic];
when I tried
textView.attributedText = [[NSAttributedString alloc] initWithString:#"blahblah" attributes:textViewAttributeDic];
It worked, but i need empty textView with no spaces or 'blah' characters
The documentation clearly states that typingAttributes is for the editing mode of the text field.
typingAttributes
The attributes to apply to new text being entered by the user.
...
If the text field is not in editing mode, this property contains the value nil. Similarly, you cannot assign a value to this property unless the text field is currently in editing mode.
Instead, you should assign attributedText instead of the text property. The mechanism to specify the attributes is via NSAttributedString that you assign.
You may configure paragraph style in IB using temporary text in text view and setting all required attributes. Then you clear your text view on launch textView.text = nil. Text attributes should remain the same.
in ios6 I solved it like this , in textView delegate I wrote:
- (void)textViewDidChange:(UITextView *)textView{
// 1st save current selected range ... we gonna use this value in 5th step
NSRange textViewCurrentRange = textView.selectedRange;
// 2nd disable scrolling in textview
[textView setScrollEnabled:NO];
// 3rd set the new enterd text as attributed string to textview
[textView setAttributedText:[[NSAttributedString alloc]initWithString:textView.text attributes:self.textAttributes]];
// 4th enable scrolling
[textView setScrollEnabled:YES];
// 5th re set selected range so text inidicator will get back to it's place
textView.selectedRange = textViewCurrentRange;
}
Programmatically setting attributedText resets the typingAttributes. Set typingAttributes last.
Here's one gotcha - as mentioned in other answers, the UITextField must be in editing mode for this to work. If you are running in the simulator, and the keyboard is hidden (cmd+k), the textfield is not in editing mode if you type using your computer's keyboard. Make sure the simulator's keyboard is displayed.
I took a hint from #Mundi's answer.
In my case, I set typingAttributes when the viewController was created, and it did not work
I was entering code according to placeholder in textViewShouldBeginEditing, so I reset typingAttributes in that method, but it didn't work the same way.
When I saw #Mundi's answer and resetting typingAttributes in textViewDidBeginEditing, it worked fine.

text editing in text view xcode

I have a text view in which text is displayed like this:
how are you?
Fine
Now if i set font for text view, then the same font is displayed for the two lines(ques and answer), however i want question to be displayed in one font and answer in some other font. How can i do this?
I set font like this:
textView = [[UITextView alloc]initWithFrame:CGRectMake(10, 80, 300, 440)];
textView.layer.borderColor = [UIColor blackColor].CGColor;
[textView setFont:[UIFont fontWithName:#"TimesNewRomanPS-ItalicMT" size:14]];
textView.layer.borderWidth = 1.0;
textView.autoresizesSubviews = YES;
textView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:textView];
Thanks in advance!!
From the UITextView class reference:
In iOS 6 and later, this class supports multiple text styles through
use of the attributedText property. (Styled text is not supported in
earlier versions of iOS.) Setting a value for this property causes the
text view to use the style information provided in the attributed
string. You can still use the font, textColor, and textAlignment
properties to set style attributes, but those properties apply to all
of the text in the text view.
This class does not support multiple styles for text. The font, color,
and text alignment attributes you specify always apply to the entire
contents of the text view. To display more complex styling in your
application, you need to use a UIWebView object and render your
content using HTML.
So you cannot have two on the same page for iOS 5 or less because it is not supported. Just use a webview and an HTML file. for iOS6 maybe you can try using attributedText property of UITextView. This is available under iOS 6. Never tried it though.
Or have 2 different UITextView's (its ugly but thats what it is).
I'm guessing you wanted to create a chatroom like app?
if so, I recommend make it a UITableView. And then make different Cells to match different styles.
You can use attributed strings to achieve this, for example:
NSMutableAttributedString *para1 = [[NSMutableAttributedString alloc] initWithString:#"How are you?"];
NSMutableAttributedString *para2 = [[NSMutableAttributedString alloc] initWithString:#"\nFine"];
[para2 setAttributes:#{ NSForegroundColorAttributeName : [UIColor blueColor]} range:NSMakeRange(0, para2.length)];
[para1 insertAttributedString:para2 atIndex:para1.length];
self.textLabel.attributedText = para1;
Or with a single attributed string:
NSMutableAttributedString *para1 = [[NSMutableAttributedString alloc] initWithString:#"How are you?\nFine"];
// Get the range of the last line in the string
__block NSRange range;
[para1.mutableString enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) {
range = [para1.mutableString rangeOfString:line];
}];
[para1 setAttributes:#{ NSForegroundColorAttributeName : [UIColor blueColor] } range:range];
self.textLabel.attributedText = para1;
Both examples result in:

Resources