UILabel appearance font and attributed string font - ios

In my app I have a global custom font applied to all labels like so:
UIFont *font = [UIFont fontWithName:kMyFontName size:15.0];
[[UILabel appearance] setFont:font];
This works fine. However, in some cases I want to be able to specify a different font for a specific region of a UILabel string.
So I have something like this:
NSString *string = #"Foo Bar Baz";
UIFont *boldFont = [UIFont fontWithName:kMyBoldFontName size:15.0];
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:string];
[attrString setAttributes:#{ NSFontAttributeName: boldFont } range:NSMakeRange(0, 3)];
self.myLabel.attributedText = attrString;
However this doesn't seem to work. I expect the "Foo" to be bold, but the entire string just has the default font. It's as if the bold font is not applied at all and is being overwritten by the font set on the UILabel appearance proxy.
When I remove the UILabel appearance line then it works fine (I can see part of the string in bold). Basically I want to have my custom font applied to the label but a separate font applied to a different region of the string. Normally this works fine with attributed strings but for some reason setting the UILabel appearance font disables this functionality (or so it seems).
Expected results: "Foo Bar Baz"
Actual results: "Foo Bar Baz"
If I remove the [[UILabel appearance] setFont:] line then it works:
"Foo Bar Baz"
(but the custom font is not set on the rest of the string).
So my question is: Is there a way to specify a single font to use as the default app-wide but still be able to partially override that using attributed strings?
Also if someone can explain to me why this is not working I'd appreciate it.

Set font and textColor to nil just before setting attributed string.

You can't mix and match attributed text and plain text; that's why removing the setFont method works - because when you use it, it assumes a plaintext UILabel.
NSString *string = #"Foo Bar Baz";
UIFont *boldFont = [UIFont fontWithName:kMyBoldFontName size:15.0];
// Define your regular font
UIFont *regularFont = [UIFont fontWithName:kMyFontName size:15.0];
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:string];
// And before you set the bold range, set your attributed string (the whole range!) to the new attributed font name
[attrString setAttributes:#{ NSFontAttributeName: regularFont } range:NSMakeRange(0, string.length - 1)];
[attrString setAttributes:#{ NSFontAttributeName: boldFont } range:NSMakeRange(0, 3)];
self.myLabel.attributedText = attrString;

There are two important parts:
UIAppearance applies at the moment of adding UI element to window
labelInstance.font = ... resets all font attributes of currently set attributed string
So if you want to keep UIAppearance customisation you have to set your custom attributed string after your label get added to window.
Reference article about how does UIAppearance work: Peter Steinberger's cool article

Related

Bold font style for custom font in iOS application

I have a custom font and it doesn't include bold face. I have no problem using it in web and Android since they use faux bold but, I don't know how can I make it bold in iOS.
I want to know if there is a way to make faux bold in iOS or any tool to create a bold font face from normal one using techniques that browsers use.
You could use NSAttributedString to stroke text and make them bold.
Try this code below:
NSString *string = #"Hello World";
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:string];
NSDictionary *attributes = #{
NSStrokeWidthAttributeName: #-5.0, //value for making bold, higher negative number bolder text
NSStrokeColorAttributeName:[UIColor blackColor],
NSForegroundColorAttributeName:[UIColor blackColor],
NSFontAttributeName:[UIFont fontWithName:#"Your font name" size:20]
};
[attrString addAttributes:attributes range:NSMakeRange(0, string.length)];
Hope this help.

Text Formatting Using UITextView

I have a UITextView where user enter data. I have a format bar below which has
bold, italic, underline and other options like alignment etc.
After a lot of search and testing I came to know that NSString don't support such bold, italic styling instead NSAttributedString should be used but I use NSAttributedString I am unable to make the selected text bold and italic at the same time.
My code is like this
NSMutableAttributedString *textViewText = [[NSMutableAttributedString alloc]initWithAttributedString:textView.attributedText];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
if(textBoldBtn){
UIFont *boldFont = [UIFont boldSystemFontOfSize:textView.font.pointSize];
NSDictionary *boldAttr = [NSDictionary dictionaryWithObject:boldFont forKey:NSFontAttributeName];
[dict addEntriesFromDictionary:boldAttr];
}
if(textItalicBtn){
UIFont *italicFont = [UIFont italicSystemFontOfSize:textView.font.pointSize];
NSDictionary *italicAttr = [NSDictionary dictionaryWithObject:italicFont forKey:NSFontAttributeName];
[dict addEntriesFromDictionary:italicAttr];
}
attributedText = [[NSMutableAttributedString alloc] initWithString:text attributes:dict];
[textViewText appendAttributedString:attributedText];
textView.attributedText = textViewText;
return true;
}
Using this technique it only takes the last font in dict when both buttons are pressed.
I have gone through a link on stack overflow where they use fontDescriptor of Label to make the text both italic and bold but note I don't want to use any label. I am using UITextView. I have also gone through
[textView setAllowsEditingTextAttributes:YES];
But I want my own functions. I have also seen several EGOTextView and TextEdit for iOS but I strictly want this for iPad. I only want to use UITextView.
Kindly tell if there is any way using attributed string to make text both italic bold and even underline at the same time or any way to customize the functions of textView personal EditingTextAttributes functionality.
Thanks in Advance.
*App has to be uploaded to app store so no private frameworks required because they would cause rejection of app.
You have a some issues.
First:
Attributes are a NSDictionary. That means works with key/value, and the key is unique!
So when, you use addEntriesFromDictionary:, the doc says:
If both dictionaries contain the same key, the receiving dictionary’s
previous value object for that key is sent a release message, and the
new value object takes its place.
And when you want to apply bold and italic effect in your code, you think that you have:
Key — Value
NSFontAttributeName — theBoldFont
NSFontAttributeName — theItalicFont
Whereas you replace the bold font with the italic one.
Second:
Since Bold AND Italic are a attribute "hidden" in UIFont, if you want to apply the both effect, you have to find a font which is italic AND bold. That why, underlining (NSUnderlineAttributeName) can be added without encountering your issue with bold and italic.
You may look there to know how to do about it.
So you may code some logic like this:
if (textItalicBtn && textBoldBtn)
{}
else if (textItalicBtn)
{}
else if (textBoldBtn)
{}

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

Format text in UITextView

I am making an "About Page" for my application, and I have to paste pretty huge amount of text on that page (text will not be editable).
I am using a UITextView for this purpose. However, I need some words to be in bold (like headings). But I am not able to achieve it. The UITextView removes all my formatting.
I have no code to show here because I am pasting all my text in the IB only.
Is there any workaround?? For example.. I want the heading in bold..
"About ABC Corporation
gkskgsagdfgfskgfjkgfgljdgsfjgdsjfgdjlsgflgdslgfljdsgfljgdsjlgfljdsgfljdgslfgls.
jdfjkhdsjlfhdlsfhkldshfkldshflkdhlkfhdklsfhlksdhflkdshflkhdsflkhsdklfhlksdhflkshf
fjhdshfkldshfkldhsfklhdsklfhlkdshfklhdsklfhdklsfhkdshfklhdsklfhklsdfhkldshfkhdsklf
fhjdgfkdgsjkfgjkdsgfjkdsgjfgjdkgfjgsjdfgjkdsgfjkgsdjkfgjsdgfjgsdjkfgjksdgfjkgskjfgs"
First keep text property of textView as 'Attributed', after that just select the text and change it's style and font as you want.
P.S. - All you have to do this in Attribute inspector panel of IB.
EDIT:
For more, visit this link .
Also, this is very good mainly when the textField have a text that will not change, e.g. - like About info. And when this text is inserted in IB directly instead of assigning text programmaticaly.
You can use NSAttributedString, Set Text Font, Foreground And Background Colors, StrikeThrough And Shadow etc..
Attributed strings make an association between characters and their attributes. Like NSString objects, there are two variations, NSAttributedString and NSMutableAttributedString. Although previous versions of iOS supported attributed strings, it wasn’t until iOS 6 that controls such as buttons, labels, textfields and textviews defined a property to manage attributes. Attributes are applied to a range of characters, so you can for example, set a strikethrough attribute for just a portion of a string. It’s also important to note that the default font for attributed string objects is Helvetica 12-point. Keep this in mind if you set the font attribute for a range other than the complete string. The following attributes can be set with attributed strings:
NSString *const NSFontAttributeName;
NSString *const NSParagraphStyleAttributeName;
NSString *const NSForegroundColorAttributeName;
NSString *const NSBackgroundColorAttributeName;
NSString *const NSLigatureAttributeName;
NSString *const NSKernAttributeName;
NSString *const NSStrikethroughStyleAttributeName;
NSString *const NSUnderlineStyleAttributeName;
NSString *const NSStrokeColorAttributeName;
NSString *const NSStrokeWidthAttributeName;
NSString *const NSShadowAttributeName;
NSString *const NSVerticalGlyphFormAttributeName;
// Create attributed string
NSString *str = #"example for underline \nexample for font \nexample for bold \nexample for italics";
NSMutableAttributedString *attributedString =
[[NSMutableAttributedString alloc] initWithString:str];
// Add attribute NSUnderlineStyleAttributeName
[attributedString addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:NSUnderlineStyleSingle]
range:NSMakeRange(12, 9)];
[attributedString addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:NSUnderlineStyleSingle]
range:NSMakeRange(12, 9)];
// Set background color for entire range
[attributedString addAttribute:NSBackgroundColorAttributeName
value:[UIColor yellowColor]
range:NSMakeRange(0, [attributedString length])];
// Create NSMutableParagraphStyle object
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.alignment = NSTextAlignmentCenter;
// Add attribute NSParagraphStyleAttributeName
[attributedString addAttribute:NSParagraphStyleAttributeName
value:paragraph
range:NSMakeRange(0, [attributedString length])];
// Set font, notice the range is for the whole string
UIFont *font = [UIFont fontWithName:#"Helvetica" size:18];
[attributedString addAttribute:NSFontAttributeName
value:font
range:NSMakeRange(35, 4)];
// Set font, notice the range is for the whole string
UIFont *fontBold = [UIFont fontWithName:#"Helvetica-Bold" size:18];
[attributedString addAttribute:NSFontAttributeName
value:fontBold
range:NSMakeRange(53, 4)];
// Set font, notice the range is for the whole string
UIFont *fontItalics = [UIFont fontWithName:#"Helvetica-Oblique" size:18];
[attributedString addAttribute:NSFontAttributeName
value:fontItalics
range:NSMakeRange(71, 7)];
// Set label text to attributed string
[self.mytextView setAttributedText:attributedString];
Check out attributedText property of UITextView
https://developer.apple.com/library/ios/documentation/uikit/reference/uitextview_class/Reference/UITextView.html#//apple_ref/occ/instp/UITextView/attributedText
And this how you can make part of your string bold
Any way to bold part of a NSString?
You can use NSMutableAttributedString to support multi attribute property to your string.Note:- NSMutableAttributedString is available in iOS 6.0+. Edit:- Check this:- How to create a UILabel or UITextView with bold and normal text in it?
iOS SDK has included text kit in it.
iOS 7 offers the ability to enhance the legibility of text by increasing font weight, as well as an option to set the preferred font size for apps that support dynamic text. Users will expect apps written for iOS7 to honor these settings, so ignore them at your own risk!
In order to make use of dynamic type you need to specify fonts using styles rather than explicitly stating the font name and size. With iOS 7 a new method has been added to UIFont, preferredFontForTextStyle that creates a font for the given style using the user’s font preferences.
Here is a great tutorial in great website Ray wenderlich text kit tutorial
If you have time, watch WWDC 2013 video session 201
UITextView is a plain text and you can't apply different styles(font,color) for different words.
I suggest you to use UIWebView. It is html, so it can be styled.

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