How to set custom bold font programmatically - swift - ios

I am trying to set the font in a UILabel to a custom font but also make it bold without success. My effort so far is below:
CUSTOM FONT:
cell.folderName.font = UIFont.init(name: "American Typewriter", size: 20)
How do I make the above font also bold/ or italic?

This enum can be used for AmericanTypewriter type.
public enum americanTypewriter: String {
case typewriter = "AmericanTypewriter"
case bold = "AmericanTypewriter-Bold"
case condensed = "AmericanTypewriter-Condensed"
case condensedBold = "AmericanTypewriter-CondensedBold"
case condensedLight = "AmericanTypewriter-CondensedLight"
case light = "AmericanTypewriter-Light"
public func font(size: CGFloat) -> UIFont {
return UIFont(name: self.rawValue, size: size)!
}
}
For Bold
cell.folderName.font = UIFont.init(name: "AmericanTypewriter-Bold", size: 20)

Font American Typewriter doesn't have italic style. But it has bold style.
So if you need to set bold font, just use
"AmericanTypewriter-Bold"
All American Typewriter font's styles:
AmericanTypewriter-CondensedBold
AmericanTypewriter-Condensed
AmericanTypewriter-CondensedLight
AmericanTypewriter
AmericanTypewriter-Bold
AmericanTypewriter-Semibold
AmericanTypewriter-Light

Related

Custom font for semantic fonts styles such as headline, body, etc?

I want to use the semantic font styles, but also want to use a custom font. Is this possible so I can continue using .font(.headline) in the code but using my own custom font?
add your custom fonts to your project:
add your custom fonts to your project's info.plist:
Add extension:
extension NSAttributedString.Key {
public enum SourceSansPro: String {
case black = "SourceSansPro-Black"
case blackItalic = "SourceSansPro-BlackIt"
case bold = "SourceSansPro-Bold"
case boldItalic = "SourceSansPro-BoldIt"
case extraLight = "SourceSansPro-ExtraLight"
case extraLightItalic = "SourceSansPro-ExtraLightIt"
case italic = "SourceSansPro-It"
case light = "SourceSansPro-Light"
case lightItalic = "SourceSansPro-LightIt"
case regular = "SourceSansPro-Regular"
case semibold = "SourceSansPro-Semibold"
case semiboldItalic = "SourceSansPro-SemiboldIt"
}
}
Add extension:
extension Font {
static func my(font: NSAttributedString.Key.SourceSansPro, size: CGFloat) -> Font {
return self.custom(font.rawValue, size: size)
}
}
Use:
Text("Title")
.font(.my(font: .bold, size: 17))

What is the system font of iOS13?

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.

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

How do I get a monospace font that respects acessibility settings

let bodyFontDescriptor = UIFontDescriptor
.preferredFontDescriptor(withTextStyle: UIFontTextStyle.body)
let bodyMonospacedFontDescriptor = bodyFontDescriptor.addingAttributes(
[
UIFontDescriptorFeatureSettingsAttribute: [
[
UIFontFeatureTypeIdentifierKey: kTextSpacingType,
UIFontFeatureSelectorIdentifierKey: kMonospacedTextSelector
]
]
])
let bodyMonospacedFont = UIFont(descriptor: bodyMonospacedFontDescriptor, size: 0.0)
textview.font = bodyMonospacedFont
This produces text with characters of variable width.
I need to get a monospace font without hardcoding courier new
and fixed size.
Deployment target is ios 9.0
Here is an extension to UIFontDescriptor that returns a preferred monospaced font descriptor for a given text style. There is no simple way to get a fully monospaced font using UIFont or UIFontDescriptor. This solution attempts to find a good monospaced font and falls back to Courier if needed.
extension UIFontDescriptor {
static let monoDescriptor: UIFontDescriptor = {
// Attempt to find a good monospaced, non-bold, non-italic font
for family in UIFont.familyNames {
for name in UIFont.fontNames(forFamilyName: family) {
let f = UIFont(name: name, size: 12)!
let fd = f.fontDescriptor
let st = fd.symbolicTraits
if st.contains(.traitMonoSpace) && !st.contains(.traitBold) && !st.contains(.traitItalic) && !st.contains(.traitExpanded) && !st.contains(.traitCondensed) {
return fd
}
}
}
return UIFontDescriptor(name: "Courier", size: 0) // fallback
}()
class func preferredMonoFontDescriptor(withTextStyle style: UIFontTextStyle) -> UIFontDescriptor {
// Use the following line if you need a fully monospaced font
let monoDescriptor = UIFontDescriptor.monoDescriptor
// Use the following two lines if you only need monospaced digits in the font
//let monoDigitFont = UIFont.monospacedDigitSystemFont(ofSize: 0, weight: .regular)
//let monoDescriptor = monoDigitFont.fontDescriptor
// Get the non-monospaced preferred font
let defaultFontDescriptor = preferredFontDescriptor(withTextStyle: style)
// Remove any attributes that specify a font family or name and remove the usage
// This will leave other attributes such as size and weight, etc.
var fontAttrs = defaultFontDescriptor.fontAttributes
fontAttrs.removeValue(forKey: .family)
fontAttrs.removeValue(forKey: .name)
fontAttrs.removeValue(forKey: .init(rawValue: "NSCTFontUIUsageAttribute"))
let monospacedFontDescriptor = monoDescriptor.addingAttributes(fontAttrs)
return monospacedFontDescriptor.withSymbolicTraits(defaultFontDescriptor.symbolicTraits) ?? monospacedFontDescriptor
}
}
Note the comments about whether you need a font that is fully monospaced or a font that just has monospaced digits. Comment/Uncomment those lines to suit your specific needs.
Sample usage:
let bodyMonospacedFont = UIFont(descriptor: .preferredMonoFontDescriptor(withTextStyle: .body), size: 0)
textview.font = bodyMonospacedFont
The following is some test code to confirm that the results of preferredMonoFontDescriptor(withTextStyle:) works properly for all styles:
let textStyles: [UIFontTextStyle] = [ .body, .callout, .caption1, .caption2, .footnote, .headline, .subheadline, .largeTitle, .title1, .title2, .title3 ]
for style in textStyles {
let nfont = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: style), size: 0)
let mfont = UIFont(descriptor: .preferredMonoFontDescriptor(withTextStyle: style), size: 0)
print(style)
print(nfont)
print(mfont)
}
If you compare each pair of results, they have the same size, weight, and style, just a different font.

Resources