Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force view controller to reload to refresh UIAppearance changes

Tags:

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.

like image 599
The Lone Fellow Avatar asked Jan 02 '14 01:01

The Lone Fellow


People also ask

How do I load a view view controller?

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.


Video Answer


2 Answers

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

like image 79
David 'mArm' Ansermot Avatar answered Sep 28 '22 05:09

David 'mArm' Ansermot


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.

like image 34
Petr Dvořák Avatar answered Sep 28 '22 06:09

Petr Dvořák