-->

UIAppearance's “when not contained in”

2020-08-12 16:35发布

问题:

I am currently spinning a complex web of UIAppearance modifiers*, and have come across a problem.

My usage of FlatUIKit's custom UIBarButton appearance protocol is causing MFMailComposerViewController to complain and stop working.

Therefore, instead of using UIAppearance's whenContainedIn method to specify classes that cause modification to occur, is there a way to exclude certain classes, i.e. a "when not contained in"?

*I am talking about the UIAppearance protocol that is used to predefine object appearance settings in the app's delegate.

回答1:

You can use appearanceWhenContainedIn: to specify nil modification, which will give the default appearance:

[[UIBarButton appearance] setBarTintColor:[UIColor redColor]];
[[UIBarButton appearanceWhenContainedIn:[MFMailComposerViewController class], nil] setBarTintColor:nil];

As of iOS 9 SDK, there is also

[[UIBarButton appearance] setBarTintColor:[UIColor redColor]];
[[UIBarButton appearanceWhenContainedInInstancesOfClasses:@[[MFMailComposerViewController class]] setBarTintColor:nil];

Which can be used Swift-2 like so:

UIBarButton.appearance().barTintColor = UIColor.redColor()
UIBarButton.appearanceWhenContainedInInstancesOfClasses([MFMailComposerViewController.self]).barTintColor = nil


回答2:

For me I used this one which works in iOS 10,

[[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTextColor:[UIColor darkGrayColor]];


回答3:

My solution is to create a custom subclass of all the container view controllers that are being used in the app as the main UIWindow subviews (window's root view controller or presented view controllers), such as UINavigationController, UITabBarController or UISplitViewController.

Let's say the app is only using UINavigationController. Create a subclass:

class CustomizedNavigationController: UINavigationController {}

Then use the CustomizedNavigationController instead of plain UINavigationController everywhere in the app.

Also, instead of specifying the appearance for every UIBarButton, specify the appearance only when contained in the subclass:

UIBarButtonItem.appearance(whenContainedInInstancesOf: 
                           [CustomizedNavigationController.self])

Because MFMailComposerViewController is not using the subclass, it won't get customized.