Search code examples
iosswiftuiappearance

appearanceWhenContainedIn in Swift


I'm trying to convert my app to the Swift language.

I have this line of code:

[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil]
                     setTitleTextAttributes:textDictionary
                                   forState:UIControlStateNormal];

How to convert it to Swift?

In Apple's docs, there is no such method.


Solution

  • Update for iOS 9:

    If you're targeting iOS 9+ (as of Xcode 7 b1), there is a new method in the UIAppearance protocol which does not use varargs:

    static func appearanceWhenContainedInInstancesOfClasses(containerTypes: [AnyObject.Type]) -> Self
    

    Which can be used like so:

    UITextField.appearanceWhenContainedInInstancesOfClasses([MyViewController.self]).keyboardAppearance = .Light
    

    If you still need to support iOS 8 or earlier, use the following original answer to this question.

    For iOS 8 & 7:

    These methods are not available to Swift because Obj-C varargs methods are not compatible with Swift (see http://www.openradar.me/17302764).

    I wrote a non-variadic workaround which works in Swift (I repeated the same method for UIBarItem, which doesn't descend from UIView):

    // UIAppearance+Swift.h
    #import <UIKit/UIKit.h>
    NS_ASSUME_NONNULL_BEGIN
    @interface UIView (UIViewAppearance_Swift)
    // appearanceWhenContainedIn: is not available in Swift. This fixes that.
    + (instancetype)my_appearanceWhenContainedIn:(Class<UIAppearanceContainer>)containerClass;
    @end
    NS_ASSUME_NONNULL_END
    

    // UIAppearance+Swift.m
    #import "UIAppearance+Swift.h"
    @implementation UIView (UIViewAppearance_Swift)
    + (instancetype)my_appearanceWhenContainedIn:(Class<UIAppearanceContainer>)containerClass {
        return [self appearanceWhenContainedIn:containerClass, nil];
    }
    @end
    

    Just be sure to #import "UIAppearance+Swift.h" in your bridging header.

    Then, to call from Swift (for example):

    # Swift 2.x:
    UITextField.my_appearanceWhenContainedIn(MyViewController.self).keyboardAppearance = .Light
    
    # Swift 3.x:
    UITextField.my_appearanceWhenContained(in: MyViewController.self).keyboardAppearance = .light