2016-05-13 10 views
-1

У меня есть UITableViewController с некоторыми пользовательскими ячейками и UIView в каждой ячейке. Я внедрил контроллер cellForRowAtIndexPath для настройки UIView в каждой ячейке. Для этого мне нужно знать ширину UIView на экране. Поскольку я использую классы автоопределения и размера для автоматического изменения размера UIView на основе ориентации устройства, я внедрил дополнительный метод получения времени выполнения ширины.Размер автоопределения UIView, указанный в неправильном классе размеров, впервые

Проблема в том, что, когда представление таблицы представлено в первый раз, мой код сообщает ширину для UIVIew из класса компактной ширины, даже когда я использую устройство в альбомной ориентации. Система отображает все представления как следует, но мой код для получения ширины не работает. Прокрутка новых ячеек, видимых или изменение ориентации, немедленно устранит ситуацию.

Мой код:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

      // ... 

      CustomCell* cell = [tableView dequeueReusableCellWithIdentifier:@"CustomCell"]; 

      if (cell == nil) { 
       NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil]; 
       cell = [nib firstObject]; 
      } else { 

       // Clear custom content 

       NSArray *viewsToRemove = [cell.histogramView subviews]; 
       for (UIView *v in viewsToRemove) { 
        [v removeFromSuperview]; 
       } 
      } 

      [cell setNeedsLayout]; 
      [cell layoutIfNeeded]; 

      int width = ((CustomView*)cell.customView).getWidth; 
      NSLog(@"width = %d", width); 

      // ... 

} 

И потом:

@implementation CustomView 

- (int)getWidth { 
    [self setNeedsLayout]; 
    [self layoutIfNeeded]; 

    int width = self.frame.size.width; 
    return width; 
} 

@end 

Edited добавить:

Проблема, кажется, что в том, когда cellForRowAtIndexPath называется первый раз появляется TableView, autolayout для ячейки не произошло. Принудительно с помощью [cell setNeedsLayout] и [cell layoutIfNeeded] сразу после создания ячейки тоже не делается.

Похоже, что моя основная причина проблемы - это потенциальный дубликат How to know the width of an UITableViewCell when using auto layout?. Так что проблема связана с тем, что, когда мой CustomCell загружается из nib, у него будет рамка по умолчанию. Специальные трюки должны быть сделаны, чтобы принудительно отключить автозапуск. Однако принятый ответ не работает для ячеек, которые изначально выходят из видимой области. Все берут на себя это?

+0

Когда это называется? Убедитесь, что он находится в viewDidAppear или позже.Если он вызван в viewWillAppear или viewDidLoad, он пока не будет определен. –

+0

Он вызывается из cellForRowAtIndexPath, поскольку он необходим для настройки содержимого ячейки. Вызов отображается в фрагменте. – AntonBoer

+0

Почему вы не используете автозапуск, зависящий от размера, для вашего пользовательского контента в ячейке? – fabe

ответ

0

я узнал правильное решение этой проблемы:

  1. Создать пользовательскую ячейку, как в исходном вопросе.
  2. Набор cell.contentMode = UIViewContentModeRedraw в tableview: cellForRowAtIndexPath:
  3. Реализовать layoutSubviews для пользовательской ячейки, как так:

    - (void)layoutSubviews { [super layoutSubviews]; NSLog(@"cell width == %f", self.bounds.size.width); }

Таким образом, вы будете иметь доступ к размеру ячейки, как она будет отображаться на экране ,

0

Я бы предложил попытаться использовать ограничения и отношения вместо фактической ширины кадра, так как, как заявил Маркус Адамс, кадр будет иметь значение, которое вы действительно ищете только после viewDidAppear.

Например, если ваши ячейки содержат UILabel, которая равна 1/3 ширины ячейки, и UIImageView, который заполняет оставшееся пространство, вы можете установить ограничения между ними и родительским представлением.

Можете ли вы изменить эту логику следующим образом?

Еще одно предложение - вызвать reloadData в представлении таблицы после viewDidAppear, но это определенно не очень хороший вариант UX-мудрый.

+0

Благодарим вас за ответ. UIView внутри моей ячейки имеет постоянные ограничения на ширину, установленную с помощью раскадровки. Книжные и ландшафтные режимы (классы размера) будут иметь раздельную ширину. Как я могу определить, какой из них будет использоваться для отображения UIView во время cellForRowAtIndexPath, чтобы правильно настроить содержимое UIView, которые зависят от времени выполнения измерений? – AntonBoer

+0

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

+0

Итак, предположим, что у UIView есть UITableViewCell. Для одного класса размера (портрет) я хочу, чтобы ширина UIView была равна 100. Для другого класса размера (пейзаж) я хочу, чтобы UIView имел ширину 150. Я установил это, и он работает. Теперь, я должен заполнить UIView тем, что я хочу, который не может быть настроен с автозапуском. Чтобы реализовать это, мне нужен способ исследовать время выполнения ширины UIView. Проблема только в том, что когда ячейка и UIView собираются появиться и загрузиться из наконечника, автоопределение не произошло, а ширина по умолчанию от элемента nib сообщается во время cellForRowAtIndexPath. – AntonBoer