CoreText - Performance warning when creating a CTFont? - objective-c

I get the following warning when creating a CTFont.
CoreText performance note: Client requested font with PostScript name "ArialRoundedMTBold" using name "Arial Rounded MT Bold" instead.
// Creating Font
CTFontRef fontWithoutTrait = CTFontCreateWithName((__bridge CFStringRef)(name), size, NULL);
// Font names I use to create a font
[UIFont familyNames];
Is it safe to assume that if I remove all spaces in any of the font names taken from [UIFont familyNames] it'll be the expected font-name by core text?

Ended up converting full name to postscript name when creating the font.
+ (NSString *)postscriptNameFromFullName:(NSString *)fullName
{
UIFont *font = [UIFont fontWithName:fullName size:1];
return (__bridge NSString *)(CTFontCopyPostScriptName((__bridge CTFontRef)(font)));
}

Related

Objective c UIFont systemFontOfSize does not work

I am trying to change text font size with using NSAttributedString. But it's size doesn't change.
NSDictionary *attrDict = #{NSFontAttributeName : [UIFont boldSystemFontOfSize:22], NSForegroundColorAttributeName : [UIColor orangeColor]};
NSAttributedString *newAttString = [[NSAttributedString alloc] initWithString:mytext attributes:attrDict];
[result appendAttributedString:newAttString];
Only text color changes. Size of result string is not 22 and also it is not bold.
Instead of applying the attributes with the alloc, init, try doing it after with something like (with a mutable NSAttributedString):
NSMutableAttributedString *newAtt = [[NSMutableAttributedString alloc] initWithString:mytext]; // Allocate a new NSMutableAttributedString with `mytext`
[newAtt addAttributes:#{NSFontAttributeName : [UIFont boldSystemFontOfSize:20],
NSForegroundColorAttributeName: [UIColor orangeColor]}
range:NSMakeRange(0, [result length])]; // add new attributes for the length of the string `mytext`
[result setAttributedText:newAtt];
This answer would vary depending on what result is, I tested it on a UITextView and it worked fine, there is also an attributedText
property on UILabels.
Hope this helps.
You didn't mention what result means at the end of your code. Are you sure you want to "append" it?
Besides, I use this code for setting fonts
[UIFont fontWithName:#"Arial-BoldMT" size:22.0f]
This can be used to set different fonts and sizes respectively.
Hope this helps:)

UIFont fontWithName return nil

This code return Me nil in font.
I add the open sans ttf file to project folder.
What am I missing?
UIFont *font = [UIFont fontWithName:#"OpenSans-Bold" size:fontSize];
if (font)
{
[str addAttribute:NSFontAttributeName value:[UIFont fontWithName:font size:fontSize] range:NSMakeRange(location, length)];
label.attributedText = str;
}
First of all are your .ttf files registered in your .plist file ?
Second are your fonts added to "Copy Bundle Resources" ? (Under Target->Build Phases)
Next try this code to list all usable fonts and their names. This way you can make sure you use the right identifier for your font.
for (NSString* fontFamily in [UIFont familyNames]) {
NSArray *fontNames = [UIFont fontNamesForFamilyName:fontFamily];
NSLog (#"%#: %#", fontFamily, fontNames);
}
Edit
Since this answer is a bit old I updated it with the corresponding answer for Swift 3.0:
_ = UIFont.familyNames.map {
let fontNames = UIFont.fontNames(forFamilyName: $0)
print("Font Family: \($0), Font Names: \(fontNames)\n")
}

Use medieval (lowercase, non-lining) numbers

I have a request from a customer to use a certain font in a iOS 7 project because it has medieval numbers.
Is there any way to activate those numbers for a NSAttributedString? As default lining numbers are used, that are included in the font as-well.
Here is an example. Both lines have the same font with no variant (Regular), once with medieval numbers activated, the second wit the default lining numbers.
These are called lowercase numbers and can be turned on using UIFontDescriptor.
First, you need to import CoreText for some constants:
#import <CoreText/SFNTLayoutTypes.h>
or
#import CoreText.SFNTLayoutTypes;
Then create font using font descriptor. Here I use Georgia family:
NSDictionary *lowercaseNumbers = #{
UIFontFeatureTypeIdentifierKey: #(kNumberCaseType),
UIFontFeatureSelectorIdentifierKey: #(kLowerCaseNumbersSelector),
};
UIFontDescriptor *descriptor = [[UIFontDescriptor alloc] initWithFontAttributes:
#{
UIFontDescriptorFamilyAttribute: #"Georgia",
UIFontDescriptorFeatureSettingsAttribute:#[ lowercaseNumbers ],
}];
UIFont *font = [UIFont fontWithDescriptor:descriptor size:15];
Result:
Edit: As #Random832 pointed out, Georgia has only lowercase numbers, so the result is irrelevant. However, #vikingosegundo confirmed this code works on supported fonts. Thanks.
The top line was generated with
UIFont *font = [UIFont fontWithName:#"DIN Next LT Pro" size:12];
if (font)
label.font = font;
the second line with
NSDictionary *lowercaseNumbers = #{ UIFontFeatureTypeIdentifierKey:#(kNumberCaseType), UIFontFeatureSelectorIdentifierKey: #(kLowerCaseNumbersSelector)};
UIFontDescriptor *descriptor = [[UIFontDescriptor alloc] initWithFontAttributes:
#{UIFontDescriptorFamilyAttribute: #"DIN Next LT Pro",UIFontDescriptorFeatureSettingsAttribute:#[ lowercaseNumbers ]}];
UIFont *font = [UIFont fontWithDescriptor:descriptor size:12];
if (font)
label.font = font;
Another question has a pointer in the right direction, though the question mentions tabular figures [vs proportional] rather than text vs lining.
It looks like you can use CTFontDescriptorCreateCopyWithFeature with kNumberCaseType set to kLowerCaseNumbersSelector to display the digits this way.
Here's another related question, and here's the blog post provided in the answer.

Handling UIContentSizeCategoryDidChangeNotification for NSAttributedString in UITextView

I have an NSAttributedString in a UITextView and would like to handle the UIContentSizeCategoryDidChangeNotification when working with Dynamic Type and specifically the text styles. All the examples I've seen (IntroToTextKitDemo) address the case where the font is the same for the whole UI element. Does anyone know how to handle this properly so all the attributes update properly?
Note: I asked this on the developer forums when iOS 7 was under NDA. I'm posting it here because I found a solution and thought others might find it useful.
I found a solution. When handling the notification you need to walk the attributes and look for the text styles and update the font:
- (void)preferredContentSizeChanged:(NSNotification *)aNotification
{
UITextView *textView = <the text view holding your attributed text>
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:textView.attributedText];
NSRange range = NSMakeRange(0, attributedString.length - 1);
// Walk the string's attributes
[attributedString enumerateAttributesInRange:range options:NSAttributedStringEnumerationReverse usingBlock:
^(NSDictionary *attributes, NSRange range, BOOL *stop) {
// Find the font descriptor which is based on the old font size change
NSMutableDictionary *mutableAttributes = [NSMutableDictionary dictionaryWithDictionary:attributes];
UIFont *font = mutableAttributes[#"NSFont"];
UIFontDescriptor *fontDescriptor = font.fontDescriptor;
// Get the text style and get a new font descriptor based on the style and update font size
id styleAttribute = [fontDescriptor objectForKey:UIFontDescriptorTextStyleAttribute];
UIFontDescriptor *newFontDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:styleAttribute];
// Get the new font from the new font descriptor and update the font attribute over the range
UIFont *newFont = [UIFont fontWithDescriptor:newFontDescriptor size:0.0];
[attributedString addAttribute:NSFontAttributeName value:newFont range:range];
}];
textView.attributedText = attributedString;
}

Change font for string with object in Objective C

I am bringing in some data from a JSON file and I want to change the font to courier but when I try to do the following I get this error: "Property 'font' not found on object NSString". Is there any way around this?
NSString *timePeriod = [diction objectForKey:#"Time Period"];
UIFont *changeFont = [UIFont fontWithName:#"Courier" size:12];
timePeriod.font = changeFont;
A font is part of an attributed string.
NSMutableAttributedString timeSringWithAttr = [[NSMutableAttributedString alloc] initWithString:timeString];
[timeStringWithAttr addAttribute:NSFontAttributeName
value:changeFont
range:NSRangeFromString(timeString)];
NSString just stores strings, it has no knowledge of fonts. If you want to set the font when you draw the string use the NSString AppKit additions:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSString_AppKitAdditions/Reference/Reference.html#//apple_ref/doc/uid/20000155
Basically, you want to set the font when you draw the string to screen.
The NSString class doesn't have font property, and it shouldn't since every String object is an array of characters.
Instead, use UILabel or UITextView, depends on your needs with text in it, and set font property on them.
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 50)];
label.text = #"YOUR_TEXT";
label.font = [UIFont fontWithName:#"Courier" size:12.0f];
And in convention you shouldn't name variables with verb names, those are for functions.
Like UIFont *changeFont..