Search code examples
ioscocoa-touchuiappearance

When can I start using properties set using UIAppearance?


I have some custom appearance properties in my view class (a descendant of UIView). I want to customize the view appearance according to these properties, but I can’t do that inside the initializer, since the values set using [[MyClass appearance] setFoo:…] aren’t in effect at that point:

@interface View : UIView
@property(strong) UIColor *someColor UI_APPEARANCE_SELECTOR;
@end

@implementation View
@synthesize someColor;

// Somewhere in other code before the initializer is called:
// [[View appearance] setSomeColor:[UIColor blackColor]];

- (id) initWithFrame: (CGRect) frame
{
    self = [super initWithFrame:frame];
    NSLog(@"%@", someColor); // nil
    return self;
}

@end

They are already set in layoutSubviews, but that’s not a good point to perform the view customizations, since some customizations may trigger layoutSubviews again, leading to an endless loop.

So, what’s a good point to perform the customizations? Or is there a way to trigger the code that applies the appearance values?


Solution

  • One possible workaround is to grab the value directly from the proxy:

    - (id) initWithFrame: (CGRect) frame
    {
        self = [super initWithFrame:frame];
        NSLog(@"%@", [[View appearance] someColor); // not nil
        return self;
    }
    

    Of course this kills the option to vary the appearance according to the view container and is generally ugly. Second option I found is to perform the customizations in the setter:

    - (void) setSomeColor: (UIColor*) newColor
    {
        someColor = newColor;
        // do whatever is needed
    }
    

    Still I’d rather have some hook that gets called after the appearance properties are set.