问题
I'm working on a swift app and I wanna change the UIStatusBarStyle
according to the app's theme (there are 2 options - light and dark theme). I have set View controller-based status bar appearance
to NO
in the info.plist
and in the UIViewController
I tried to set it based on the current theme like so:
override var preferredStatusBarStyle: UIStatusBarStyle {
return Theme.current.statusBarStyle
}
protocol ThemeProtocol {
// Status Bar
var statusBarStyle: UIStatusBarStyle { get }
}
class Theme {
static var current: ThemeProtocol = LightTheme()
}
class LightTheme: ThemeProtocol {
// Status Bar
var statusBarStyle: UIStatusBarStyle = .default
}
class DarkTheme: ThemeProtocol {
// Status Bar
var statusBarStyle: UIStatusBarStyle = .lightContent
}
No result really. I tried to test it by returning only: return .lightContent
but that didn't change the status bar either.
What am I doing wrong?
UPDATE:
Okay, so this is what I'm trying to do and it's not working.
fileprivate func applyTheme() {
statusBarStyle = UserDefaults.standard.bool(forKey: SelectedThemeKey) ? .default : .lightContent
self.setNeedsStatusBarAppearanceUpdate()
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return statusBarStyle
}
And it's not working. Despite changing the theme, the status bar always remain with the default style. applyTheme()
is called in viewDidLoad()
and viewWillAppear()
回答1:
You need to call this method after any change
setNeedsStatusBarAppearanceUpdate()
//
class ViewController: UIViewController {
var current = UIStatusBarStyle.default
@IBAction func changeClicked(_ sender: Any) {
current = current == .default ? .lightContent : .default
self.setNeedsStatusBarAppearanceUpdate()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return current
}
}
回答2:
First of all, your code makes no sense. You say
I have set View controller-based status bar appearance to NO in the info.plist and in the UIViewController I tried to set it
So on the one hand you tell the runtime, do not listen to my view controller. Then you complain when the runtime doesn't listen to your view controller!
Second, keep in mind that your view controller gets no say in the status bar appearance unless it is the top-level view controller (or the top-level view controller deliberately defers to it). If your view controller is inside a navigation controller, for example, its statusBarStyle
is completely irrelevant.
回答3:
First
if you are trying to change StatusBarStyle
with UIApplication.shared.statusBarStyle = .default
, then you should set
View controller-based status bar appearance
to be NO
.
in this way, you need to control UIApplication.shared.statusBarStyle
by yourself in everywhere; e.g viewWillAppear
/ viewWillDisappear
.
but this method is deprecated after iOS 9.
Now I suggest you learn the new way:
please set View controller-based status bar appearance
to be YES
, and
override UIViewController
's preferredStatusBarStyle
to handle it.
override var preferredStatusBarStyle: UIStatusBarStyle {
return .default
}
but it still not working, why?
in your case, I guess that UIViewController
is one of viewControllers
of UINavigationController
.
if you used UINavigationController
, you should override preferredStatusBarStyle
in UINavigationController
.
maybe you will say that I need to set different status bar style with difference view controllers, it is okay.
Just override childForStatusBarStyle
in UINavigationController
like this
override var childForStatusBarStyle: UIViewController? {
return topViewController
}
then override preferredStatusBarStyle
in UIViewController
you want to change.
you can also make it by extension
like this
extension UINavigationController {
override open var childForStatusBarStyle: UIViewController? {
return topViewController
}
}
来源:https://stackoverflow.com/questions/51799469/uistatusbarstyle-doesnt-change