iosswiftfontscore-textuifont

How to display non-slashed zero character in Swift for the system font SF Mono


The system font SF Mono has two variations for the number zero (0) and number one (1).

By default, a slashed zero character is displayed for text with system font SF Mono.

In the MacOS Font Book, both a slashed zero and non-slashed zero have the code U+0030.

How can I specify a non-slashed zero on a UIButton title in Swift?

Thanks!


Example of a non-slashed zero character:

enter image description here


Solution

  • This answer uses the Stylistic Alternatives feature in CoreText.


    Source:

    This link describes the set of currently defined typographic and layout features available from applications using CoreText.

    https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type35


    Try this code:

    import UIKit
    
    class ViewController: UIViewController {
        
        // Set the status bar of the view to hidden
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            self.setNeedsStatusBarAppearanceUpdate()
        }
        override var prefersStatusBarHidden : Bool {
            return true
        }
        override var childForStatusBarHidden : UIViewController? {
            return nil
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            
            // Set the background color of the view to systemGray5
            view.backgroundColor = .systemGray5
    
            // Create a UIButton
            let button = UIButton(type: .system)
    
            // Set the title of the button to "100"
            button.setTitle("100", for: .normal)
    
            // Set the font of the button title to SFMono with a size of 150
            button.titleLabel?.font = UIFont.monospacedSystemFont(ofSize: 150, weight: .regular)
    
            // Set the background color of the button to systemYellow
            button.backgroundColor = .systemYellow
    
            // Set the tint color of the button to black
            button.tintColor = .black
    
            // Make the button rounded by setting its corner radius to 25
            button.layer.cornerRadius = 25
    
            // Ensure that the rounded corners are displayed correctly
            button.clipsToBounds = true
    
            // Define the font descriptor for the custom font
            let fontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body).withDesign(.monospaced)?.addingAttributes([
                .featureSettings: [
                    
                    // Set the stylistic alternative for "0"
                    [
                    UIFontDescriptor.FeatureKey.type: kStylisticAlternativesType,
                    UIFontDescriptor.FeatureKey.selector: kStylisticAltThreeOnSelector
                    ],
                    
                    // Set the stylistic alternative for "1"
                    [
                    UIFontDescriptor.FeatureKey.type: kStylisticAlternativesType,
                    UIFontDescriptor.FeatureKey.selector: kStylisticAltFourOnSelector
                ]
                    
                ]
            ])
    
            // Create the custom font
            let font = UIFont(descriptor: fontDescriptor!, size: 150)
    
            // Create an attributed string with the custom font
            let attributedString = NSAttributedString(string: "100", attributes: [.font: font])
    
            // Apply the attributed string to the button
            button.setAttributedTitle(attributedString, for: .normal)
    
            // Add the button to the view
            view.addSubview(button)
    
            // Center the button in the view
            button.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
                button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
            ])
        }
    }
    

    Running the code displaying stylistic alternatives for "0" and "1":

    enter image description here