Search code examples
iosswiftuisegmentedcontrol

Why are fonts in UI segment control reverting to system fonts automatically?


I have several UI Segment Controls across an iOS app written in swift.

Whilst simulating on an iOS device, on the initial load they use the correct custom font set in the code but certain instances where I go to other views and come back, the fonts in the segment control tabs seem to revert to system fonts automatically.

What is causing this issue?

I am creating all of my segmented controls using this function in each view controller. This is where the custom fonts are set.

    override func viewDidLoad() {
    super.viewDidLoad()
    isHirer = AppSettings.boolValue(.isHirer)
    setupUI()
    setupSegmentControl()
    downloadData()
    configureLocationManager()
    
}



    func setupSegmentControl() {
    var items = [String]()
    
    items = AppSettings.boolValue(.isHirer) ? ["Posts", "Manage"] : ["Search", "Manage"]
    
    let segmentedControl = UISegmentedControl(items: items)
    segmentedControl.selectedSegmentIndex = 0
    UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor:UIColor.init(displayP3Red: 0/255, green: 0/255, blue: 0/255, alpha: 1), NSAttributedString.Key.font : UIFont.init(name: "Cabin-SemiBold", size: 16)!], for: .selected)
    UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor:UIColor.init(displayP3Red: 138/255, green: 145/255, blue: 172/255, alpha: 0.7), NSAttributedString.Key.font : UIFont.init(name: "Cabin-SemiBold", size: 16)!], for: .normal)
    segmentedControl.frame = CGRect.init(x: 0, y: 42, width: tableView.frame.width/2-20, height: 48)
    
    
    if AppSettings.boolValue(.isHirer) {
        segmentedControl.setContentOffset(CGSize(width: 0, height: -5), forSegmentAt: 0)
        segmentedControl.setContentOffset(CGSize(width: 0, height: -5), forSegmentAt: 1)
    } else {
        segmentedControl.setContentOffset(CGSize(width: 5, height: -5), forSegmentAt: 0)
        segmentedControl.setContentOffset(CGSize(width: 0, height: -5), forSegmentAt: 1)
    }

    
    segmentedControl.setBackgroundImage(backgroundWithColor(color: .backgroundGray, frame: CGRect(x: 0, y: 0, width: segmentedControl.frame.width, height: segmentedControl.frame.height)), for: .normal, barMetrics: .default)
    segmentedControl.setDividerImage(imageWithColor(color: UIColor.white), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
    segmentedControl.addTarget(self, action: #selector(showSection), for: .valueChanged)
    seg = segmentedControl
}

@objc func showSection(sender: UISegmentedControl) {
    switch sender.selectedSegmentIndex {
    case 0:
        isSegment0 = true
        tableView.reloadData()
    case 1:
        isSegment0 = false
        tableView.reloadData()
    default:
        break
    }
}

Then in ViewForHeaderInSection function of table view added seg to the header view.

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    
    if section == 0 && AppSettings.boolValue(.isHirer) || section == 0 && !AppSettings.boolValue(.isHirer) {
        let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 90))
        headerView.backgroundColor = .backgroundGray
   

        
        let segmentControl = seg
        segmentControl.tag = section

        headerView.addSubview(segmentControl)

        return headerView

Solution

  • Please try modifying your code as follows:

    Before:

    UISegmentedControl.appearance().setTitleTextAttributes(...)
    

    After:

    segmentedControl.setTitleTextAttributes(...)
    

    i.e. do not use appearance proxy on the UISegmentedControl class

    The appearance proxy would typically be done once in an app early in its lifecycle before any controls of that class are instantiated. For example, you might instead use the appearance proxy in your AppDelegates didFinishLaunching() API, this would replace the need to call setTitleTextAttributes() elsewhere in your code.

    Please report back if this helps.