2013-08-05 4 views
2

Я следующие настройкиНеправильный размер этикетки на viewWillAppear

  • XIB файл, который имеет только вид ландшафта. Этот вид является подключением к моему контроллеру.
  • На этом изображении есть метка, которая подключена к IBOutlet UILabel* label
  • Эта метка сконфигурирована следующим образом (она занимает всю ширину экрана). enter image description here
  • Я переопределил viewWillAppear и сделаю это (чтобы получить размер метки).
-(void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 

    CGRect rect = _labelTitleLand.frame; 
} 

Странная вещь (которую я не понимаю). То, что он возвращает size = (ширина 768, высота 21), когда он запускается в портрете (на iPad), что является правильным.

И он возвращает размер = (ширина 741 высота 21), когда он запускается в ландшафте. Что странно. Я ожидал, что он вернет ширину 1024, высота 21 для пейзажа.

У меня было впечатление, что в момент просмотраWillAppear все размеры элементов управления уже рассчитаны.

Update 1

Если я проверить labelTitleLand.frame на viewDidAppear, то он возвращает правильные результаты. Однако мне это не нравится, потому что я хочу сделать некоторые действия (на основе этого размера), которые влияют на то, как будет отображаться представление. В случае, если я сделаю это на viewDidAppear, как я понимаю, будет видимая перерисовка.

+0

Попробуйте использовать _labelTitleLand.bounds и посмотрите, работает ли это. – rdelmar

+0

@rdelmar: Он возвращает тот же результат –

ответ

8

Макет иерархии вида должен быть заполнен, прежде чем вы получите фактические конечные кадры.

Итак, вы должны проверить фрейм в viewDidLayoutSubviews, который все равно будет до того, как будет нарисована иерархия вида. Если вам нужно внести изменения здесь, вы можете не вызывать перерисовки.

viewWillAppear слишком рано, потому что это происходит до того, как ваши авторезистирующие маски (и/или ограничения автоопределения) имеют эффект.

+0

Спасибо. Отличный ответ. КСТАТИ. Есть ли хорошее руководство, которое описывает это? –

0

Это похоже на проблему, связанную с тем, когда метод фактически вызывается во время выполнения.

я решил подобную ситуацию, используя

[self performSelector:@selector(checkMethod) withObject:nil afterDelay:0.1]; 

в viewWillAppear, а затем:

- (void)checkMethod 
{ 
    rect = _labelTitleLand.frame; 
} 

Это дает ваше приложение время, необходимое для установки его собственный кадр. Это не так элегантно, и это похоже на обходное решение, но оно очень эффективно.

Вы также можете попытаться заставить кадр UIView, который является контейнером из UILabel в viewWillAppear, как это:

-(void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 

    self.view.frame = CGRectMake(0.0f, 0.0f, 1024.0f, 768.0f); 

    CGRect rect = _labelTitleLand.frame; 
} 

Но первое решение является более надежным и, как правило, никакого отставания не испытывается.

+0

Задержка в 100 мс, которую вы вводите, в большинстве случаев, вероятно, достаточна для завершения макета. Но вместо того, чтобы догадываться об этом, вы можете просто использовать метод 'viewDidLayoutSubviews', который вызывается именно тогда, когда макет завершен, и до того, как представления отображаются на экране. –

+0

viewDidLayoutSubviews должен работать, но только если вы нацеливаете> = iOS5 ... – Beppe

+0

да, конечно, если OP по-прежнему необходимо поддерживать iOS4, то это не вариант. –

Смежные вопросы