Когда применяются классы размера UIView для загрузки UIView непосредственно из Xib?

Я запускаю UIView с помощью xib программно:

- (id)initWithFrame:(CGRect)frame
{
    self = [[[NSBundle mainBundle] loadNibNamed:@"MyViewNib" owner:self options:nil] objectAtIndex:0];
    if (self)
    {
        //perform setup of various components

        return self;
    }
}

В этом представлении используются классы размеров для любой ширины, любой высоты и любой ширины, компактной высоты.

У меня есть UIButton в xib, на фоне которого мне нужно поместить круг, например:

self.closeButton.layer.cornerRadius = self.closeButton.frame.size.width / 2.0f;
self.closeButton.layer.backgroundColor = [UIColor colorWithWhite:164.0f / 255.0f alpha:1.0f].CGColor;

Если я попытаюсь установить угловой радиус кнопки в функции инициализации, когда я нахожусь на устройстве, использующем любую ширину, компактную высоту, рамка метки по-прежнему имеет значение «Любая ширина, любая высота». Я также пытался переопределить layoutSubviews и установить там значение, но безуспешно. Похоже, что ограничения класса размера применяются после layoutSubviews без другого вызова layoutSubviews, поскольку другие компоненты отображаются на экране правильно.

Итак, мне интересно, есть ли для меня хорошая точка входа, чтобы понять, где применяются классы размера, чтобы я мог правильно установить радиус угла фона кнопки. Я мог бы просто настроить кнопку программно, но я хотел бы выяснить, как это сделать, поскольку она, вероятно, снова появится в процессе преобразования в классы размеров.


person DivideByZer0    schedule 08.07.2015    source источник


Ответы (5)


В вашем классе xib -(void)awakeFromNib;

person TheSD    schedule 08.07.2015
comment
Похоже, что awakeFromNib вызывается, как только вызывается функция загрузки Xib, то есть даже до тела инициализации if (self). - person DivideByZer0; 08.07.2015

Это работает, если я поставлю его в конец функции инициализации:

 [self performSelector:@selector(updateButtonBackground) withObject:nil afterDelay:.001];

По-видимому, к этому моменту ограничения были установлены с классами размеров. Это, безусловно, неидеально, поэтому, если у кого-то есть ответ, основанный на событиях или связанный с представлением «жизненного цикла» (насколько это применимо к UIView), я соглашусь с этим...

person DivideByZer0    schedule 08.07.2015

Как насчет этого?

-(void)layoutSubviews
{
    [super layoutSubviews];
self.closeButton.layer.cornerRadius = self.closeButton.frame.size.width / 2.0f;
self.closeButton.layer.backgroundColor = [UIColor colorWithWhite:164.0f / 255.0f alpha:1.0f].CGColor;
//more of your changes
[self layoutIfNeeded]; // You can remove this line if it works without it for you..
}
person Subbu    schedule 08.07.2015
comment
Не повезло там; он по-прежнему устанавливает угловой радиус на основе любого размера экрана... - person DivideByZer0; 10.07.2015

Я знаю, что эта тема устарела, но я не вижу здесь хорошего ответа.

Классы размера определяются в методе traitCollectionDidChange:. Вы не можете гарантировать, что traitCollection установлен в initWithFrame: или awakeFromNib:. Поэтому установите радиус угла в методе traitCollectionDidChange: на основе классов размера представления.

person vmeyer    schedule 30.10.2017

Вам нужно применить радиус угла в viewDidLayoutSubviews. Именно в этот момент вы знаете, что границы кнопки установлены.

Вы можете увидеть пример в моем блоге.

person Lawrence MacFadyen    schedule 29.09.2015
comment
Это для программно инициализированного представления из xib, и помещение его в viewDidLayoutSubviews, похоже, не работает... - person DivideByZer0; 01.10.2015
comment
Вы упомянули, что делаете классы размеров для любой ширины, любой высоты и любой ширины, компактной высоты. Это будет означать, что единственный раз, когда вы увидите разницу между Any/Any, будет любой из iPhone в ландшафтном режиме. Вы запускаете в портретном режиме на iPhone, а затем поворачиваете в альбомный режим, и в этом случае viewDidLayoutSubviews не работает? - person Lawrence MacFadyen; 01.10.2015
comment
Нет поворота, кажется, проблема в том, что представление настроено на любой, любой размер даже в/после viewDidLayoutSubviews... Мне пахнет ошибкой! - person DivideByZer0; 02.10.2015
comment
Он по-прежнему будет Any to Any после viewDidLayoutSubviews, если вы не повернете его в альбомную ориентацию или не запустите в альбомной ориентации на основе ваших классов размера. Было бы интересно посмотреть, что произойдет с классом размера для компактной ширины/любой высоты, чтобы его размер был правильным в портретной ориентации. - person Lawrence MacFadyen; 02.10.2015