Позиция UILabel в UITableViewCell завершается с первой попытки

Как только мои ноги мокрые с развитием iOS, поэтому я надеюсь, что я получу правильный уровень детализации здесь...

У меня есть UILabel, загруженный в ячейку таблицы, созданную с помощью .xib. На самом деле несколько ярлыков, одна из которых имеет разную длину (и, следовательно, меняет обернутую высоту). heightForRowAtIndexPath и т.д. должным образом переопределены, а требуемая высота для обеих меток вычисляется правильно и назначается каждому .frame

Как только оба размера были установлены, я устанавливаю frame.origin.y меньшего (фиксированная длина, всегда одна строка с высокой) меткой, чтобы соответствовать ярлыку большей метки. Это работает, насколько можно видеть, переходя через cellForRowAtIndexPath, но при первоначальном отображении вновь созданной ячейки начало координат в контейнере не является вертикально-центрированным, а не сверху.

После нажатия "через" ячейку на другое представление и возврата к контейнеру (теперь повторно используемому и предположительно уже подходящему размеру) позиция устанавливается как раньше, и она появляется там, где я ожидал.

Кажется, что размер контейнера изменяется после возврата cellForRowAtIndexPath и что где-то там найдена новая позиция для нашего ярлыка; это объясняет, почему повторное использование ячейки позже устраняет проблему.

Я пробовал все, казалось бы, разумные комбинации внутренних и внешних настроек режима и базовой линии, настройки растяжения и т.д. Потеря для объяснений и/или обходных путей.

Update:

Предложение о Изменение позиции пользовательского UIButton в пользовательском UITableViewCell разрешило проблему. Решение заключалось в подклассе UITableViewCell и переопределении layoutSubviews, тем самым получив возможность повторно позиционировать подэлементы после того, как TableView выполнил свое нормальное позиционирование. Закроет это один раз, или тот человек ответит здесь, или истекает срок, и я отвечу сам, с кодом.

Ответ 1

Если я делаю какой-либо сложный макет в UITableViewCell, я стараюсь не использовать его для cellForRowAtIndexPath. Один из вариантов - сделать макет в - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath, но я предпочитаю инкапсулировать макет в пользовательский класс UITableViewCell.

Создайте свой собственный подкласс UITableViewCell. Создайте и добавьте пользовательскую кнопку/метку/представление в элемент содержимого cellView в методе init, или создайте и добавьте его лениво через свойство accessor. Переопределите layoutSubviews и разместите кнопку по желанию.

Что-то вроде этого:

@implementation MyCustomCell

- (void) init
{
    self = [super initWithStyle: UITableViewCellStyleDefault reuseIdentifier: nil];
    if ( self != nil )  
    {
         _myButton = [[UIButton buttonWithType: UIButtonTypeRoundedRect] retain];
         [self.contentView addSubview: _myButton];
    }

    return self;
}

- (void) layoutSubviews
{
    [super layoutSubviews];

    // dynamic layout logic:
    if ( ... )
    {

         _myButton.frame = CGRectMake( 10, 10, 100, 30 );
    }
    else 
   {
         _myButton.frame = CGRectMake( 20, 10, 50, 30 );

   }
}

Ответ 2

Я также столкнулся с подобной проблемой.

Размещение кода в этом методе работало для меня.

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
// here.
}