What is the system font of iOS13? - ios

What is the iOS 13 system font?
Before iOS 13 I used SFUIDisplay font.
UIFont(name: ".SFUIDisplay-Light", size: UIFont.systemFontSize)
But on iOS 13 it doesn't work.

This bug is so BS. The only way to get around it is by using the systemFont(ofSize:weight:) method directly. AKA, you cannot get the system font using the method UIFont(name:size:), you ll just get Times New Roman for some funny reason. Apple devs must be messing with us. So for the original question above you must use the following:
UIFont(systemFont:UIFont.systemFontSize, weight: .light)
For my situation, I ran into this bug making an extension for UIFont to return the same font in a different size, which must work with custom and system fonts. In order for it to work on xcode 11 ios 13, I had to add a silly check to see if fontName contains ".SF".
extension UIFont {
func forSize(_ pointSize: CGFloat) -> UIFont {
if !fontName.contains(".SF"), let font = UIFont(name: fontName, size: pointSize) {
return font
}
return UIFont.systemFont(ofSize: pointSize, weight: weight)
}
}

If you are aiming to use the system font, you don't really have to worry about its name, you should let the system to do it for you.
let font = UIFont.systemFont(ofSize: UIFont.systemFontSize)
At this point, whenever the system font changes, it will automatically updated.
Moreover
I use a lot of custom fonts. I need to do it
Actually, you could do it without mentioning the font name in case you want to use the system font. For example, you could implement a function that returns the proper font as:
func getFont(name: String = "", size: CGFloat = UIFont.systemFontSize) -> UIFont {
// system font
let defaultFont = UIFont.systemFont(ofSize: UIFont.systemFontSize)
if name.isEmpty {
return defaultFont
}
return UIFont(name: name, size: size) ?? defaultFont
}
For using the system font, call it: getFont(). Otherwise, call it with mentioning the name of the font: getFont(name: ".SFUIDisplay-Light").
However, you might think of doing something like this to get the system font name and then use it:
let systemFontName = UIFont.systemFont(ofSize: UIFont.systemFontSize).fontName
getFont(name: systemFontName)
I'd say it's meaningless since the UIFont.systemFont automatically detects the system font name without the need of mentioning it.

font-family: ".SFCompactText-Regular"; font-weight: normal; font-style: normal

It's "San Francisco (SF) Pro and Compact" font. You can check here https://developer.apple.com/fonts/

Create a font using systemFont(ofSize: CGFloat) -> UIFont.
Then get the fontName and familyName of that font.
Print the above and you have the answer for the current iOS; so run it on iOS 13.

Related

iOS using custom Arabic/Cyrillic fonts automatically

I'm trying to learn if it is possible to use a custom Arabic and Cyrillic fonts without having to do a switch/if-else on the user's language setting.
I can successfully use my custom font in the app. I'd like to supply a custom Ar/Cy font the same way, and I know I could build it into the app. If I have my font SpecialFont.otf and also supply SpecialFont-CY.otf how would the OS know to use SpecialFontCY.otf when the user is using a Cyrillic language? Ideally the OS will know the user's primary font and would be able to select a font that matches/includes the correct glyphs for the language.
PS. this is not a question on how to use a custom font, I can do that. I want to know how to supply multiple fonts for various languages to fully support the world without writing code like this:
if NSLocale.preferredLanguages.first == "Arabic"
let myFont = UIFont(name:"SpecialFont-AR", size: 17)
else if NSLocale.preferredLanguages.first == "Russian"
let myFont = UIFont(name:"SpecialFont-CY", size: 17)
...etc
Rather than using a UIFont, you want a UIFontDescriptor. With that you can set the font attribute cascadeList, which tells the system what order to select fonts based on glyph availability (i.e. look in SpecialFont, but if you can't find a glyph for ب, try SpecialFont-CY, and then SpecialFont-AR).
The point of a cascade list is to select the correct font for a given glyph. This way, if a string contains Cyrillic, Arabic, and Latin mixed together, it'll still work fine.
For example:
// Start with your base font
let font = UIFont(name:"SpecialFont", size: 17)!
// Create the ordered cascade list.
let cascadeList = [
UIFontDescriptor(fontAttributes: [.name: "SpecialFont-AR"]),
UIFontDescriptor(fontAttributes: [.name: "SpecialFont-CY"]),
]
// Create a new font descriptor based on your existing font, but adding the cascade list
let cascadedFontDescriptor = font.fontDescriptor.addingAttributes([.cascadeList: cascadeList])
// Make a new font base on this descriptor
let cascadedFont = UIFont(descriptor: cascadedFontDescriptor, size: font.pointSize)
This is covered in detail in Creating Apps for a Global Audience (WWDC 2018).
No you can't, but you can define a simple extension to DRY your code:
extension UIFont {
static func preferred(ofSize size: CGFloat) -> UIFont{
switch NSLocale.preferredLanguages.first {
case "Arabic": return UIFont(name:"SpecialFont-AR", size: size)!
case "Russian": return UIFont(name:"SpecialFont-CY", size: size)!
default: return UIFont.systemFont(ofSize: size) // etc.
}
}
}
Now all you have to do is:
let myFont = UIFont.preferred(ofSize: 17)
You will need to check this somehow in order to determine what is the right language to set.
If you don't want to use if/else syntax, you can use Ternary Conditional Operator.
let myFont = (NSLocale.preferredLanguages.first == "Arabic") ? UIFont(name:"SpecialFont-AR", size: 17) : UIFont(name:"SpecialFont-CY", size: 17)
Or more readable, like this:
let fontName = (NSLocale.preferredLanguages.first == "Arabic") ? "SpecialFont-AR" : "SpecialFont-CY"
let myFont = UIFont(name: fontName, size: 17)

Set Specific Font Weight for UILabel in Swift

When people have asked how to set a bold font, most people suggest:
let boldFont = UIFont.boldSystemFont(ofSize: ___)
But take a look at all the font weights that the standard system font offers:
So my question is how do you set a light, semibold, or heavy font weight? The only way that I know how is:
sectionLabel.font = [UIFont fontWithName:#"TrebuchetMS-Bold" size:18];
However, I'm still asking because this isn't strongly typed. Most other class attributes are set by selecting from a fixed set of options and don't require passing a string that I could mistype. I guess I could set my own global enum... But any better ideas?
I couldn't get the UIFontDescriptor to work with the font weight trait but there is another approach.
let font = UIFont.systemFont(ofSize: 20, weight: .light)
Replace .light with whichever value you want from UIFont.Weight which basically matches the dropdown list shown in your question.
You can use this extension. It assigns the weight to the fontDescriptor's weight key and instantiate your font with this new descriptor.
extension UIFont {
func withWeight(_ weight: UIFont.Weight) -> UIFont {
let newDescriptor = fontDescriptor.addingAttributes([.traits: [
UIFontDescriptor.TraitKey.weight: weight]
])
return UIFont(descriptor: newDescriptor, size: pointSize)
}
}
The very old thread, but someone may be interested in how to do it in Swift.
UIFont.Weight defines all of the options:
ultraLight
thin
light
regular
medium
semibold
bold
heavy
black
you can use simply like that, e.g.:
label.font = UIFont.systemFont(ofSize: size, weight: .bold)
or if you want to keep the previous size:
label.font = UIFont.systemFont(ofSize: label.font!.pointSize, weight: .bold)
Even more:
let font = UIFont.systemFont(ofSize: 20, weight: UIFont.Weight(500))
If you want to use system fonts, for Swift 5 a simple extension would look like this:
extension UIFont {
func withWeight(_ weight: UIFont.Weight) -> UIFont {
UIFont.systemFont(ofSize: pointSize, weight: weight)
}
}

Font in iOS11 is incorrectly displayed

I have a font called Poppins-bold (you can find it on Google Font) that in iOS 11 display incorrectly. Here you can see a screenshot with iOS 10:
And screenshot in iOS 11:
Four fonts displayed are:
Poppins Bold with a Storyboard
Helvetica Bold with a Storyboard
Poppins Regular via code
Poppins Bold via code
And my error is with Poppins Bold via code. My code is:
label1.font = UIFont(name: "Poppins-Regular", size: 30)
label2.font = UIFont(name: "Poppins", size: 30)
How is it possible?
I've printed font in the projects and this is my result:
Font Family Name = [Poppins]
Font Names = [["Poppins-Regular", "Poppins"]]
Your printout explains the problem. "Poppins" is a family name. If you have both Poppins Regular and Poppins Bold, the family name defaults to meaning the regular font. This prevents you from accessing the Poppins Bold font by its name, which (unfortunately) is "Poppins".
Instead, use the font descriptor to change Poppins Regular to Poppins Bold:
let font = UIFont(name: "Poppins-Regular", size: 30)!
let desc = font.fontDescriptor
let desc2 = desc.withSymbolicTraits(.traitBold)!
let font2 = UIFont(descriptor: desc2, size: 0)
self.lab.font = font2
I might be a bit late, but in case your question is still relevant, problem can be solved by updating font files from https://fonts.google.com/specimen/Poppins. You will also need to use "Poppins-Bold" font name instead of "Poppins".

Swift Changing font programmatically

Hi I am currently setting up views below:
func setupViews() {
self.numberLabel = UILabel(frame: .zero)
self.addSubview(self.numberLabel)
self.numberLabel.snp.makeConstraints { (make) in
make.edges.equalToSuperview()
}
self.numberLabel.textAlignment = .center
self.numberLabel.textColor = UIColor.white
self.numberLabel.adjustsFontSizeToFitWidth = true
self.numberLabel.minimumScaleFactor = 0.5
}
I would like to change the font of the text inside the label to bold font, however it's difficult to see an easy way to do so, following the syntax principles above.
For Swift 5+ and upto latest version (Swift 5.4) period
Stylizing the Font (SystemFont)
UIFont.systemFont(ofSize: 17, weight: .medium)
where you can set .weight provides various UIFont.Weight properties as given below
.black
.bold
.heavy
.light
.medium
.regular
.semibold
.thin (Looks very cool and I guess Apple also uses this somewhere)
.ultralight
Note that it's only for default SystemFont only.
AppleDocumentation
Changing the Font
UIFont(name: "HelveticaNeue-Thin", size: 16.0)
where name includes the FontName
you can also specify .weight by writing - before weight (If that font supports that weight as Not all fontFamily supports all
types of UIFont.Weight)
This is more preferable method to use for stylising the font if
you're not using default SystemFont
You just set the font property of the label, for example:
numberLabel.font = UIFont.systemFont(ofSize: 10, weight: 200)
I'm amazed there's nothing on SO already on this.
Take a look at the reference docs too: https://developer.apple.com/documentation/uikit/uilabel
By the way, unless you are operating within a closure, or other contexts where the semantics are ambiguous (e.g. in an initialiser) you don't generally need to use self. prefix.
Hope that helps.
If your just using the system font you can also do
UIFont.boldSystemFont(ofSize: 16.0)
Selecting whichever size you need
Here's the documentation on it

Swift NSAttributedString custom fonts

I've read around for different solutions but nothing seems to work. This code creates a nil exception:
[NSFontAttributeName: UIFont(name: "Raleway-SemiBold", size: 16)!]
I have the fonts installed properly and they show up correctly in the app (target is set).
I tried to add the application provided fonts in the plist but nothing happened. I can't edit the items in the array: (they are item0 : string : Raleway-SemiBold.tff).
So basically I'm stuck... Sometimes Swift and Apple environments are great for a programmer, other times (most of the time), they are sooo faulty and need so many workarounds to reach the expected results.
Many thanks in advance for any help.
You're getting an exception because UIFont(name: "Raleway-SemiBold", size: 16) returns nil and you're force-unwrapping it with !.
Instead, use conditional unwrapping:
if let font = UIFont(name: "Raleway-SemiBold", size: 16) {
let attributes = [NSFontAttributeName: font]
// do something with attributes
} else {
// The font "Raleway-SemiBold" is not found
}
You can use UIFont's familyNames() and fontNamesForFamilyName(_:) methods to get the exact string required.
Swift 4
if let font = UIFont(name: "Raleway-SemiBold", size: 16) {
let attributes = [NSAttributedStringKey.font: font]
// do something with attributes
} else {
// The font "Raleway-SemiBold" is not found
}
You Just have to write the correct string name of your font.
Don't write the name that is font file name. (like bodoni-mt-bold.ttf its the file name i have downloaded from any site).
To find out the exact font name follow the image below.
Go to your label select it and go to custom font and then see the name of your custom font in its family. if your custom font name is there then copy that name and past it as a string where u wanna use it. (Note you can't copy font name text you have to write else where then past it)
For Swift 3, here's an update that worked for me:
First you'll set up the font and then create a textAttribute with the NSFontAttributeName:
let font = UIFont(name: "Raleway-SemiBold", size: 16)
textAttribute = [NSFontAttributeName: font as Any, NSForegroundColorAttributeName: UIColor.black]
You can then apply textAttribute to your label, textfield etc.

Resources