I know that to set a custom font of an element on the screen I can simply dosomeLabel.font=UIFont(name: \"Exo 2.0\", size: 15)
.
I was wondering how one
You can set the appearance of the UILabel and other UIViews:
UILabel.appearance().font = UIFont(name: "yourFont", size: yourSize)
More General:
AnyUIView.appearance().font = UIFont(name: "yourFont", size: yourSize)
As a more detailed answer and with these benefits I recommend using extensions:
import UIKit
extension UILabel {
@objc var substituteFontName : String {
get {
return self.font.fontName;
}
set {
let fontNameToTest = self.font.fontName.lowercased();
var fontName = newValue;
if fontNameToTest.range(of: "bold") != nil {
fontName += "-Bold";
} else if fontNameToTest.range(of: "medium") != nil {
fontName += "-Medium";
} else if fontNameToTest.range(of: "light") != nil {
fontName += "-Light";
} else if fontNameToTest.range(of: "ultralight") != nil {
fontName += "-UltraLight";
}
self.font = UIFont(name: fontName, size: self.font.pointSize)
}
}
}
extension UITextView {
@objc var substituteFontName : String {
get {
return self.font?.fontName ?? "";
}
set {
let fontNameToTest = self.font?.fontName.lowercased() ?? "";
var fontName = newValue;
if fontNameToTest.range(of: "bold") != nil {
fontName += "-Bold";
} else if fontNameToTest.range(of: "medium") != nil {
fontName += "-Medium";
} else if fontNameToTest.range(of: "light") != nil {
fontName += "-Light";
} else if fontNameToTest.range(of: "ultralight") != nil {
fontName += "-UltraLight";
}
self.font = UIFont(name: fontName, size: self.font?.pointSize ?? 17)
}
}
}
extension UITextField {
@objc var substituteFontName : String {
get {
return self.font?.fontName ?? "";
}
set {
let fontNameToTest = self.font?.fontName.lowercased() ?? "";
var fontName = newValue;
if fontNameToTest.range(of: "bold") != nil {
fontName += "-Bold";
} else if fontNameToTest.range(of: "medium") != nil {
fontName += "-Medium";
} else if fontNameToTest.range(of: "light") != nil {
fontName += "-Light";
} else if fontNameToTest.range(of: "ultralight") != nil {
fontName += "-UltraLight";
}
self.font = UIFont(name: fontName, size: self.font?.pointSize ?? 17)
}
}
}
Samples for using Extensions:
e.g. put these lines in your starting controller viewDidLoad
UILabel.appearance().substituteFontName = "IRANSans"; // USE YOUR FONT NAME INSTEAD
UITextView.appearance().substituteFontName = "IRANSans"; // USE YOUR FONT NAME INSTEAD
UITextField.appearance().substituteFontName = "IRANSans"; // USE YOUR FONT NAME INSTEAD
P.S. as @Christian mentioned, you can write your own extensions for almost AnyUIView
FINALLY figured this out. Cleanest way I could find. (Swift 4) Solution doesn't require you to set font sizes and won't override all font sizes.
UILabel.appearance().font = UIFont.preferredFont(forTextStyle: UIFontTextStyle(rawValue: "Roboto"))
For those looking for where to place this code. I put it in my AppDelegate.swift file inside of
func application(_ application: UIApplication,
didFinishLaunchingWithOptions...
Swift 4.2
UILabel.appearance().font = UIFont.preferredFont(forTextStyle: UIFont.TextStyle(rawValue: "Roboto"))
The answer is a combination of the answers offered already, but I had to try a combination of things to get it working in iOS 13:
This is all placed in a Table View Controller, which is made to conform to the UIFontPickerViewControllerDelegate in order to offer a view for the user to pick the font. This will update all the UILabels with the new font, but keep the other attributes.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
if cell === fontCell {
if #available(iOS 13, *) {
let configuration = UIFontPickerViewController.Configuration()
configuration.includeFaces = true
let fontVC = UIFontPickerViewController(configuration: configuration)
fontVC.delegate = self
present(fontVC, animated: true)
} else {
let ac = UIAlertController(title: "iOS 13 is required", message: "Custom fonts are only supported by devices running iOS 13 or above.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
}
}
}
@available(iOS 13.0, *)
extension AppearanceTableViewController: UIFontPickerViewControllerDelegate {
func fontPickerViewControllerDidPickFont(_ viewController: UIFontPickerViewController) {
// attempt to read the selected font descriptor, but exit quietly if that fails
guard let descriptor = viewController.selectedFontDescriptor else { return }
let font = UIFont(descriptor: descriptor, size: 20)
UILabel.appearance().substituteFontName = font.fontName
}
}
extension UILabel {
@objc public var substituteFontName : String {
get {
return self.font.fontName;
}
set {
let fontNameToTest = self.font.fontName.lowercased()
var fontName = newValue
if fontNameToTest.range(of: "bold") != nil {
fontName += "-Bold"
} else if fontNameToTest.range(of: "medium") != nil {
fontName += "-Medium"
} else if fontNameToTest.range(of: "light") != nil {
fontName += "-Light"
} else if fontNameToTest.range(of: "ultralight") != nil {
fontName += "-UltraLight"
}
self.font = UIFont(name: fontName, size: self.font.pointSize)
}
}
}
I found out a way to do same in Swift 4 with iOS 11
Only need to add @objc
keyword before variable name.
So variable declaration will be like this
@objc public var substituteFontName : String {
get {}
set {}
}
Hope this helps others who are facing this issue.