Set Custom Font To UILabel in iOS Swift - ios

Here, I want to set custom font(getting "Font Name" from backend) to UILabel, without adding font files in xCode project.
Please help if find any solution.
Currently I am trying with "Inkwell" in iOS. Here is the link -> https://github.com/ninjaprox/Inkwell
steps which I have followed:
Installed pod 'Inkwell', '~> 1.2'
Added Google API Key in AppDelegate like, Inkwell.shared.APIKey =
"Api key here"
import "Inkwell"
In viewWillAppear, updating label font:
let font = Font(family: "Droid Sans", variant: .regular)
fontOperation = Inkwell.shared.font(for: font, size: fontSize) { uifont in
print("Font name -> \(String(describing: uifont))")
self.lblTestFont.font = uifont ?? self.defaultFont
self.lblTestFont.text = "text"
}
But getting "Font name" nil. Font Operation failed.
How I can fix this issue?

To use custom font in iOS app you need to add those font in info.plist file and also add those font in project.
Once you do all these step then you can use the following code to check that our custom font is available to use or not.
//it will list all the fonts available
for fontFamily in UIFont.familyNames {
print(UIFont.fontNames(forFamilyName: fontFamily))
}

Related

Getting available fonts list returns warning on iOS App

I was getting available fonts with following code but I am getting this
CoreText note: Client requested name ".SFUI-Regular", it will get TimesNewRomanPSMT rather than the intended font. All system UI font access should be through proper APIs such as CTFontCreateUIFontForLanguage() or +[UIFont systemFontOfSize:].
warning many times at log recently for this line of code
let fontNames = UIFont.fontNames(forFamilyName: names)
Is there a neat way of getting rid of this.
As in warning said we are getting the same font name into the list for repeated warnings.
I filter out repeated font names later but there must be better way doing it.
var list:[String] = []
let familyNames = UIFont.familyNames
// family names
for names in familyNames {
let fontNames = UIFont.fontNames(forFamilyName: names)
// loads font names at each family fontList.count gives exact font number count
for k in 0 ..< fontNames.count {
list.append(fontNames[k])
}
}

How can you use SFPro font in Xcode for deployment target 9.3?

Xcode doesn't come with SFPro by default if we set deployment target as 9.3. The system font is SF.
I am doubtful if loading SFPro font manually will work even if I have not set deployment target as 11.
You can download the fonts here: https://developer.apple.com/fonts/
Add the font files to your project and declare them in Project Info settings with Fonts provided by application:
Then use the font with code like this (for example):
if let customFont = UIFont(name: "SFProDisplay-Regular", size: 32) {
theLabel.font = customFont
}
To find the actual names of the fonts, you can use this code:
for family in UIFont.familyNames {
let sName: String = family as String
print("family: \(sName)")
for name in UIFont.fontNames(forFamilyName: sName) {
print("name: \(name as String)")
}
}

Downloading and installing a custom font in iOS [duplicate]

This question already has answers here:
Download font .ttf file from web and store on iPhone
(5 answers)
Closed 7 years ago.
I have searched here for the answer to this but I haven't found any posts that I can use to get an answer. I have only found answers about pre-installing the font to the plist of the app which won't work for me.
What I am trying to do is download a Font from a URL, store the file locally to the app and then install or use that font in controls.
I am at the point of installing the font to the tablet to use. I can add it to CTFontManager without any issues using the code below.
private func InstallFont(dest:String)
{
let fontData = NSData(contentsOfFile: dest)!
let dataProvider = CGDataProviderCreateWithCFData(fontData)
let cgFont = CGFontCreateWithDataProvider(dataProvider)!
var error: Unmanaged<CFError>?
if !CTFontManagerRegisterGraphicsFont(cgFont, &error)
{
print("Error loading Font!")
}
}
The issue that I am facing is that I cannot seem to find the font I have installed anywhere in the app, I have tried to set it like below but just goes to default which tells me it can not be found.
self.font = UIFont(name: "Font Name", size: 20.0)
I have also looped through the font family's to see if it has been installed and no success there either.
for x in UIFont.familyNames()
{
print(x)
for z in UIFont.fontNamesForFamilyName(x)
{
print("== \(z)")
}
}
Is what I am trying to achieve even possible? If so what am I doing wrong?
It is possible. I created an example project in github. You have to just add the line below.
if !CTFontManagerRegisterGraphicsFont(cgFont, &error)
{
print("Error loading Font!")
}
else
{
let fontName = CGFontCopyPostScriptName(cgFont)
uiFont = UIFont(name: String(fontName) , size: 30)
}
Thank you for Michael Dautermann, he was right.
Github project link
According to the answers in this related question, you should be able to download your font and register it the way you are already doing (which it sounds like you are doing correctly), but you simply need to get the Postscript name and use that to create a corresponding UIFont:
var uiFont : UIFont?
let fontData = NSData(contentsOfFile: dest)!
let dataProvider = CGDataProviderCreateWithCFData(fontData)
let cgFont = CGFontCreateWithDataProvider(dataProvider)!
var error: Unmanaged<CFError>?
if !CTFontManagerRegisterGraphicsFont(cgFont, &error)
{
print("Error loading Font!")
} else {
let fontName = CGFontCopyPostScriptName(fontRef)
uiFont = UIFont(name: fontName, size: 30)
}

How do I get the font name from an otf or ttf file?

I have used a custom font in my previous app.
The file name was "ProximaNova-Regular.otf" and to load the font I just used...
[UIFont fontWithName:#"ProximaNova-Regular" size:20];
This worked perfectly.
Now in this new app I have three font files...
Dude_Willie.otf
Impact
handsean.ttf
But I'm not sure how to load these.
I have tried
[UIFont fontWithName:<the file name> size:20];
But this just falls back to using Helvetica.
How can I find what name to use?
Right click on the TTF -> Get Info
"Full Name" is what you're looking for.
That's what worked for me with TTFs.
Edit:
I just used a font that had a different name from the "Full Name" in Get Info.
For the compilation of this answer, If the quick check above doesn't work, run this code in your project:
for (NSString *fontFamilyName in [UIFont familyNames]) {
for (NSString *fontName in [UIFont fontNamesForFamilyName:fontFamilyName]) {
NSLog(#"Family: %# Font: %#", fontFamilyName, fontName);
}
}
And search for the correct name of the font you want to use.
Swift 3.0 code:
for fontFamilyName in UIFont.familyNames{
for fontName in UIFont.fontNames(forFamilyName: fontFamilyName){
print("Family: \(fontFamilyName) Font: \(fontName)")
}
}
Follow these four easy steps to add and use a new font in your iOS app:
Add your_new_font.ttf or your_new_font.otf to your Xcode project
In your project's info.plist, add a new entry for your_new_font.ttf or your_new_font.otf to the UIAppFonts array (plain text for this one is 'Fonts provided by application')
At this point, I recommend adding this temporary chunk of debug code to dump all fonts that are accessible by your app, including your newly added your_new_font:
//Swift
for family: String in UIFont.familyNames {
print("\(family)")
for names: String in UIFont.fontNames(forFamilyName: family) {
print("== \(names)")
}
}
//Objective-c
for(NSString *fontfamilyname in [UIFont familyNames]) {
NSLog(#"family:'%#'",fontfamilyname);
for(NSString *fontName in [UIFont fontNamesForFamilyName:fontfamilyname]) {
NSLog(#"\tfont:'%#'",fontName);
}
NSLog(#"-------------");
}
In the debug output, look for your new font's 'family' and 'font' name. Pass whatever is displayed as the 'font' name corresponding to your new font family (there could be more than one 'font' associated with your new font 'family') to UIFont *myNewFont = [UIFont fontWithName:#"font_name_from_debug_output" size:20] and you should be in business!
Install the font
Open Font Book app on your Mac
Select the font and click on 'info' button
The name you're looking for is PostScript name
MacOS: View -> Show Font Info
To use fonts in iOS, you have to load the font based on the font's FULL NAME (PostScript Name), which is sometimes (and usually is) different from the font's actual FILE NAME.
Imagine yourself renaming the Font file "Arial-regular.ttf" to be
"foo.ttf". The font contained inside the font file you just renamed is still
"Arial-regular".
There are some good programmatic ways to get the font name already on this thread, but I have a different approach using the command line.
If you are on a Mac or Linux, simply run this script from the command line in the directory where you have your custom fonts (uses the fc-scan utility from fontconfig which is probaly already installed, but if not you can install it via homebrew: brew install fontconfig):
for file in "$arg"*.{ttf,otf}; do fc-scan --format "%{postscriptname}\n" $file; done
Here is a screenshot of the above command running on my ~/Library/Fonts directory:
The script above will run through all the .ttf and .otf files in the current directory, then print out the PostScript Name for each font which you can use to reference the font file in XCode or elsewhere.
If you want to get fancy with some additional information (PostScriptName, Filename) and some color coding, you can run this alternative script:
for file in "$arg"*.{ttf,otf}; do
postscriptname=$(fc-scan --format "%{postscriptname}\n" $file);
printf "\033[36m PostScript Name:\033[0m %s \e[90m(%s)\033[0m\n" "$postscriptname" "$file";
done
This is a bit faster than copy-pasting code inside of your AppDelegate.m file to print out the names every time you want to add a new font file, which is the popular method, and it's also faster than opening the Font in FontBook to inspect the PostScript Name.
USEFUL TIP: If you alias the above script in your terminal so that all you need to do is type a single command to get all the PostScript font names for all the files in the current directory (my function is called fontnames so all I have to do is type fontnames at the terminal inside the directory with fonts in it, and the PostScript names will be printed automatically, then you will save time in your development workflow and have this handy script ready to use when you need it.
Hope this helps!
If you want to find the font name for a given font file programmatically:
import Foundation
func loadFontName(for file: URL) throws -> String {
let data = try Data(contentsOf: file)
guard let provider = CGDataProvider(data: data as CFData) else {
throw Error("Could not create data provider")
}
guard let font = CGFont(provider) else {
throw Error("Could not load font")
}
guard let name = font.postScriptName else {
throw Error("Could not get font name from font file")
}
return name as String
}
Replace with your own throwable Error objects as required.
Swift 4.0+ solution
for fontFamilyName in UIFont.familyNames {
print("family: \(fontFamilyName)\n")
for fontName in UIFont.fontNames(forFamilyName: fontFamilyName) {
print("font: \(fontName)")
}
}
Will output:
family: Apple SD Gothic Neo
font: AppleSDGothicNeo-Thin
font: AppleSDGothicNeo-Light
You want to know how to get name go for this :-
NSArray *familyNames = [[NSArray alloc] initWithArray:[UIFont familyNames]];
for (NSInteger indFamily=0; indFamily<[familyNames count]; ++indFamily)
{
NSLog(#"Family name: %#", [familyNames objectAtIndex:indFamily]);
NSArray *fontNames = [[NSArray alloc] initWithArray:
[UIFont fontNamesForFamilyName:[familyNames objectAtIndex:indFamily]]];
for (NSInteger indFont=0; indFont<[fontNames count]; ++indFont)
{
NSLog(#" Font name: %#", [fontNames objectAtIndex:indFont]);
}
}
hope it helps you...
Swift 3.0
for familyName in UIFont.familyNames {
for fontName in UIFont.fontNames(forFamilyName: familyName ) {
print("\(familyName) : \(fontName)")
}
}
After you've added your fonts to your project/app, add this code (probably just in app delegate didFinishLaunchingWithOptions method) in order to print out all the available fonts for your app. From with-in that list you should be able to identify the font you're after. Don't forget to remove the unnecessary code after.
for (NSString *fontFamilyName in [UIFont familyNames]) {
for (NSString *fontName in [UIFont fontNamesForFamilyName:fontFamilyName]) {
NSLog(#"Family: %# Font: %#", fontFamilyName, fontName);
}
}
You can also use otfinfo --info arial.ttf to get the name from command line. The postscript name is the one you need to pass to the UIFont constructor.
Swift 1.2:
for familyName in UIFont.familyNames() {
for fontName in UIFont.fontNamesForFamilyName(familyName as! String) {
println("\(familyName) : \(fontName)")
}
}
Another "quick, practical" hack that doesn't involve scanning through all the default fonts that exist on either the emulator or device is to use the font for something in your storyboard. Then if you edit the storyboard with a text editor (open as source code), you can see the fonts used with "internal" names if you search for the "customFonts" tag:
<customFonts key="customFonts">
<array key="Linotype - AvenirNextLTPro-Bold.otf">
<string>AvenirNextLTPro-Bold</string>
</array>
<array key="Linotype - AvenirNextLTPro-Regular.otf">
<string>AvenirNextLTPro-Regular</string>
</array>
<array key="TradeGothicLTPro-BdCn20.otf">
<string>TradeGothicLTPro-BdCn20</string>
</array>
</customFonts>
Log familyNames of font file and then access the fonts:
// You can log all font family names suing **fontNamesForFamilyName**
NSLog(#" font name %#", [UIFont fontNamesForFamilyName:#"the file name"]);
Hope it helps you.
List font names and families for macOS with Swift 4.1:
NSFontManager.shared.availableFonts.map { print($0) }
NSFontManager.shared.availableFontFamilies.map { print($0) }
Swift 4.0 Supported
This is only one line code for print all font family and it's font's names
override func viewDidLoad() {
super.viewDidLoad()
//Main line of code
UIFont.familyNames.sorted().forEach({ print($0); UIFont.fontNames(forFamilyName: $0 as String).forEach({print($0)})})
}

Customizing Font Issue in blackberry

In application i have to use custom font. First i create class that extends VerticalFieldManager class. In this class i want to use custom font. I have TTF file (name is AGENCYB.TTF). I kept this file in res/img folder. To load this file i use following code:
if (FontManager.getInstance().load("AGENCYB.TTF", "MyFont",
FontManager.APPLICATION_FONT) == FontManager.SUCCESS)
{
System.out.println("**************************IF SUCCESS*******");
try
{
FontFamily typeface = FontFamily.forName("MyFont");
myFont = typeface.getFont(Font.BOLD, 50);
label2.setFont(myFont);
}
catch (ClassNotFoundException e)
{
System.out.println(e.getMessage());
}
}
But it is not changing font of label field. I implemented code by using this link:
http://docs.blackberry.com/en/developers/deliverables/18095/BlackBerry_Java_SDK-Development_Guide--1239696-0730090812-001-6.0-US.pdf
Any idea would be great help.
Thanks
**********EDIT**************
if (FontManager.getInstance().load("AGENCYB.TTF", "AGENCYB", FontManager.APPLICATION_FONT) == FontManager.SUCCESS)
First of all, this is the BlackBerry tutorial I've used for loading custom fonts
Second of all, I don't see a return code of 8 in any of the values that the API docs says FontManager.load() returns. SUCCESS is a value of 0, so you're not successfully calling load().
http://www.blackberry.com/developers/docs/7.0.0api/net/rim/device/api/ui/FontManager.html
Returns:
FontManager.SUCCESS if font loads successfully.
FontManager.FONTS_ARRAY_FULL if too many fonts loaded.
FontManager.MISSING_TYPEFACE_NAME if typeface name is invalid.
FontManager.DUPLICATE_NAME if font name is duplicate.
FontManager.DUPLICATE_DATA if font data is duplicate.
FontManager.NO_FONT_DATA if no font data is found.
FontManager.EXCEEDS_LIMIT if font data exceeds 60k in size.
FontManager.MISS_RESOURCE if font file cannot be found.
FontManager.FAILED_TO_LOAD_FILE if font data is invalid or font format is invalid.
When I ran in the debugger on OS 5.0 and 7.1, I saw that -8 was equal to FontManager.DUPLICATE_NAME, but didn't see any code equal to 8.
Also, did you generate this font file yourself (AGENCYB.TTF)? Because your code is asking for a font named MyFont in the AGENCYB.TTF file. I wouldn't expect a font to actually be named MyFont unless it was somebody writing a Hello World program (and homemade .ttf file).
If this is a custom font, provided by a 3rd-party font library, or bought from someone else, I would expect the font names to be something other than MyFont, which is what they have in the BlackBerry sample that you probably copied your code from.
So, double-check that, and let us know if it's still not working.
Update: since it looks like you also fail when you use the string "AGENCYB" in your code, I think the problem is that you're using the wrong font name. Even though the file is AGENCYB.TTF, I bet the font name inside that file is not AGENCYB. Is this the same file that you find in Windows under C:\Windows\fonts? If so, you can use Windows (7, at least) to look at the font file.
Just double-click the .ttf file in Windows Explorer, and it should give you a preview, that shows the proper font name. That name is the name you use in the two java calls, where the sample code has "MyFont". In this case, you see that the font name is probably "Agency FB". Try that.
Update 2: I also tried loading the Agency FB font from the AGENCYR.TTF file that can be found in C:\windows\Fonts\AGENCYR.TTF on a Windows 7 machine. This exact code worked for me on a 5.0 8900 simulator:
int result = FontManager.getInstance().load("AGENCYR.TTF", "Agency FB", FontManager.APPLICATION_FONT);
if (result == FontManager.SUCCESS)
{
try
{
FontFamily typeface = FontFamily.forName("Agency FB");
Font myFont = typeface.getFont(Font.PLAIN, 50);
helloWorld.setFont(myFont);
}
catch (ClassNotFoundException ex)
{
}
}
Exactly you should check if the font desired is already loaded so it gives you a -8 or the success int and thats it!
LabelField lbl = new LabelField("This is test Label");
// IF font is already loaded then use the following
if(FontManager.getInstance().load("TickingTimebombBB_ital.ttf", "Ticking Timebomb BB", FontManager.APPLICATION_FONT) == FontManager.DUPLICATE_NAME){
Logger.debug("---font already loaded-----");
try
{
System.out.println("---load once more---");
FontFamily typeface = FontFamily.forName("Ticking Timebomb BB");
Font myFont = typeface.getFont(Font.PLAIN, 80);
lbl.setFont(myFont);
}
catch (ClassNotFoundException e)
{
Logger.error("---error-----"+e.getMessage());
}
}
and if the font is not already loaded then use the following
else if(FontManager.getInstance().load("TickingTimebombBB_ital.ttf", "Ticking Timebomb BB", FontManager.APPLICATION_FONT) == FontManager.SUCCESS) {
try
{
Logger.debug("---load first time---");
FontFamily typeface = FontFamily.forName("Ticking Timebomb BB");
Font myFont = typeface.getFont(Font.PLAIN, 80);
lbl.setFont(myFont);
}
catch (ClassNotFoundException e)
{
Logger.error("---error-----"+e.getMessage());
}
}

Resources