I have been searching for quite a while and can't find an answer. I am working on an iOS app and have a modal settings page that appears on the tap of a button and returns with a segue. One of the options I would like to implement is a color scheme setting. I really want to avoid manually changing the color for every element on the page.
Apple has a UIAppearance protocol for this sort of thing (so I can set the text color of all buttons, etc. Their documentation says:
Note: iOS applies appearance changes when a view enters a window, it doesn’t change the appearance of a view that’s already in a window. To change the appearance of a view that’s currently in a window, remove the view from the view hierarchy and then put it back.
My question is how to do this. I have tried calling viewWillAppear and setNeedsDisplay without luck.
Add views to your view controller To that root view, you add the custom views you need to present your interface. In storyboards, you add views by dragging them onto the view controller scene. For example, the following figure shows a view controller with an image view and button on an iPhone.
Try to use this snippet :
NSArray *windows = [UIApplication sharedApplication].windows; for (UIWindow *window in windows) { for (UIView *view in window.subviews) { [view removeFromSuperview]; [window addSubview:view]; } }
http://snipplr.com/view/75259/refresh-uiappearance-after-application-loaded/
It works perfect for me after changing app theme using UIAppearance
Please note that the top answer will have adverse effects on your system keyboard behavior.
It turns out that iOS creates a new system window with UITextEffectsWindow
class under the hood whenever the keyboard is displayed. If you remove it, your keyboard behavior may be negatively affected. For example, the input accessory views will be detached from the keyboard and will not be visible, except for brief flashes in the navigation controllers.
You can workaround this issue by using an additional check, like so:
for window in UIApplication.shared.windows { // Whenever a system keyboard is shown, a special internal window is created in application // window list of type UITextEffectsWindow. This kind of window cannot be safely removed without // having an adverse effect on keyboard behavior. For example, an input accessory view is // disconnected from the keyboard. Therefore, a check for this class is needed. In case this class // that is indernal is removed from the iOS SDK in future, there is a "fallback" class check on // NSString class that always fails. if !window.isKind(of: NSClassFromString("UITextEffectsWindow") ?? NSString.classForCoder()) { window.subviews.forEach { $0.removeFromSuperview() window.addSubview($0) } } }
Note that the UITextEffectsWindow
is internal and may change in the future. This is why I do not unwrap the variable using !
but provide a fallback negative NSString
class instead (no type of window is of NSString
class).
Note: For simple apps, you can probably live by using UIApplication.shared.keyWindow
for the workaround.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With