~/lxcidfollow

← writing/

Status Bar Style Not Changing in UIKit

By Stan Chang · · Updated · 2 min read · #ios-development

Status Bar Style Not Changing in UIKit

A current checklist for pushed and presented view controllers

When a status bar style does not change after a push or presentation, the usual problem is ownership. UIKit asks a particular view controller for the preferred style. An override on some other controller in the hierarchy has no effect.

Return the style from the active view controller

Override preferredStatusBarStyle on the controller that should own the appearance:

final class CustomViewController: UIViewController {
    private var usesLightStatusBar = true

    override var preferredStatusBarStyle: UIStatusBarStyle {
        usesLightStatusBar ? .lightContent : .darkContent
    }

    func setUsesLightStatusBar(_ value: Bool) {
        usesLightStatusBar = value
        setNeedsStatusBarAppearanceUpdate()
    }
}

If the value changes while the controller is visible, call setNeedsStatusBarAppearanceUpdate(). Returning a new value alone does not ask UIKit to query it again.

Forward ownership through a container

A container view controller can choose which child supplies the status bar style. If a pushed controller’s override is ignored, make the ownership explicit with childForStatusBarStyle. For example, a navigation-controller subclass can forward the query to its top controller:

final class StatusBarNavigationController: UINavigationController {
    override var childForStatusBarStyle: UIViewController? {
        topViewController
    }
}

Use the same pattern in a custom container, returning whichever child currently owns the visible content. When that child changes, ask the container to update the status bar appearance.

Capture a non-fullscreen presentation

A fullscreen presentation takes over status bar appearance. A custom, sheet, or other non-fullscreen presentation may leave control with the presenting controller. Set modalPresentationCapturesStatusBarAppearance when the presented controller should take ownership:

let presented = CustomViewController()
presented.modalPresentationStyle = .custom
presented.modalPresentationCapturesStatusBarAppearance = true
present(presented, animated: true)

Debugging checklist

  1. In Info.plist, confirm UIViewControllerBasedStatusBarAppearance is absent (the default is true) or set to true. When it is false, UIKit uses the app-level status bar style instead of the current controller’s preferredStatusBarStyle, so this controller-based checklist does not apply.
  2. Confirm the override is on the controller UIKit actually consults.
  3. If the style changes at runtime, call setNeedsStatusBarAppearanceUpdate().
  4. If a container owns the screen, return the intended child from childForStatusBarStyle.
  5. If a non-fullscreen presentation should control the style, enable modalPresentationCapturesStatusBarAppearance.
  6. Check the content behind the status bar separately. preferredStatusBarStyle changes the foreground style, not the background color or safe-area layout.

This is a UIKit guide. SwiftUI screens have a different ownership model and should not copy these container overrides blindly.

Apple documentation