Когда я могу начать использовать настройки свойств, используя UIAppearance?

У меня есть некоторые пользовательские свойства внешнего вида в моем классе вида (потомок UIView). Я хочу настроить внешний вид вида в соответствии с этими свойствами, но я не могу сделать это внутри инициализатора, так как значения, установленные с помощью [[MyClass appearance] setFoo:…] arent, действуют в этой точке:

@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, что приводит к бесконечному циклу.

Итак, что хорошего для выполнения настроек? Или есть способ инициировать код, который применяет значения внешнего вида?

Ответ 1

Возможным обходным путем является захват значения непосредственно из прокси:

- (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
}

Еще один идентификатор имеет некоторый крючок, который вызывается после того, как будут установлены свойства внешнего вида.

Ответ 2

Почему бы не подождать

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

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

если это дает вам проблемы?

Ответ 3

Предостережение: я использую Swift 2, поэтому не уверен в более ранних версиях Swift/ Objective-C. Но я обнаружил, что didMoveToSuperview() не будет работать. Свойства доступны в layoutSubviews(), но это не отличное место, чтобы делать что-либо подобное (поскольку его можно вызвать более одного раза). Лучшее место для доступа к этим свойствам в жизненном цикле вида, которое я нашел, это didMoveToWindow().

Ответ 4

Я бы подумал, что viewDidLoad было бы лучше, если бы это была единая вещь. В противном случае viewWillAppear.

EDIT:

Если вы хотите сделать это в представлении, а не в контроллере, я бы создал пользовательский init для представления по строкам:

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

тем самым передавая цвет в представление во время создания.

Ответ 5

Я полагаю, что свойства UIAppearance применяются к представлению, когда оно добавляется в иерархию представлений. Предположительно, вы можете получить доступ к заданным свойствам в UIView didMoveToSuperview.