什么时候可以开始使用使用UIAppearance设置的属性?

问题描述:

我在我的视图类(UIView的后裔)中有一些自定义的外观属性。我想根据这些属性自定义视图的外观,但我不能这样做初始化里面,因为这些值使用[[MyClass appearance] setFoo:…]设置还没有在这一点上效果:什么时候可以开始使用使用UIAppearance设置的属性?

@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 

他们是在已经设置layoutSubviews,但这不是执行视图自定义的好处,因为一些自定义可能会再次触发layoutSubviews,导致无限循环。

那么,执行定制有什么好处呢?或者是否有办法触发应用外观值的代码?

+0

我认为一旦分配了自定义类,就可以随时根据需求访问和更改成员的属性,然后可以在代码中使用修改后的信息。 –

+1

为了确保,我正在讨论通过外观代理('UIAppearance')设置的属性。这些值在初始化程序后面的某处设置。如果我在属性设置器上设置断点,我可以看到这些值是从'[CALayer layoutSublayers]'应用的。 – zoul

一个可能的解决方法是直接从代理抢值:

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

当然,这杀死根据视图容器以改变的外观的选项,通常是难看。我找到第二个选择是在二传手进行自定义设置:

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

不过我宁愿有一些钩子的外观属性设置之后被调用。

+0

看到我的答案; '钩'是UIView didMoveToSuperview :,我相信。 – TomSwift

为什么不等到

- (void)willMoveToSuperview:(UIView *)newSuperview { 
    [super willMoveToSuperview:newSuperview]; 

    if (newSuperview) { 
     ... code here ... 
    } 
} 

,如果它给你的麻烦?

+2

这是我的下一次尝试,但是这些值也没有设置在这一点上。 – zoul

我原以为viewDidLoad会是最好的,如果它是一次性的东西。否则,viewWillAppear。

编辑:

如果你想这样做的视图,而不是它的控制器,然后我会给沿线的视图自定义的初始化:

-(id) initWithFrame:(CGRect) frame andAppearanceColor:(UIColor)theColor; 

从而把颜色在创作时进入视野。

+0

这些是控制器方法,我宁愿在视图中处理它。另外,在这些调用期间很可能还没有设定值。 – zoul

+0

在初始化程序中传递颜色也不是一种选择,因为要设置更多的外观属性,并且初始化程序在控制器的外部调用... erm,* control *。有人可能会说,外观代理API的全部重点是摆脱手动设置值的所有时间。 – zoul

+0

我明白你来自哪里。也许你可以创建一个方法来设置外观属性并调用它以响应NSNotification(当指定外观属性时发送)? – ader

我相信UIAppearance属性被应用到视图时,它被添加到视图层次结构中。所以大概你可以访问UIView didMoveToSuperview中的设置属性。

警告:我使用Swift 2,所以不太确定早期版本的Swift/Objective-C。但我发现didMoveToSuperview()将无法​​正常工作。这些属性在layoutSubviews()中可用,但这不是一个很好的地方做这样的事情(因为它可以被称为不止一次)。访问这些属性的最佳地点在我发现的视图的生命周期中是didMoveToWindow()