UILabel não quebra o texto corretamente às vezes (layout automático)

Eu tenho uma configuração uilabel em uma visão. Ele não tem uma restrição de largura, mas sua largura é determinada por uma restrição principal à imagem em miniatura e uma restrição à borda da vista.

O rótulo está definido para ter 0 linhas e para quebra de linha. Meu entendimento é que isso deve fazer com que o quadro do uilabel cresça, e de fato acontece às vezes. (Anterior ao layout automático, eu iria calcular e atualizar o quadro do rótulo no código).

Então o resultado é que funciona corretamente em alguns casos e não em outros. Veja a maioria das células funcionando corretamente lá, mas a última célula parece ser muito grande. Na verdade, é o tamanho certo. O título "Fair Oaks Smog Check Test" na verdade termina com "Only". Então meu cálculo para o tamanho da célula está correto, deveria ser esse tamanho. No entanto, o rótulo não envolve o texto por qualquer motivo. A largura do quadro não se estende para a direita, então esse não é o problema.

Então, o que está acontecendo aqui? É 100% consistente, sempre nessa célula e não nas que estão acima dela, o que me faz pensar que está relacionado ao tamanho do texto, e a UILabel não está reimplantando o texto uma vez que essa visão é adicionada à célula (que torna realmente menor largura sábia).

Alguma ideia?

Alguma informação adicional

A altura das células é calculada a partir de uma célula de amostra que eu crio e armazeno em uma variável estática:

- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (self.items.count == 0) {
        return 60;
    }
    static TCAnswerBuilderCell *cell = nil;
    static dispatch_once_t pred;

    dispatch_once(&pred,
                  ^{
                      // get a sample cellonce
                      cell = [tableView dequeueReusableCellWithIdentifier:TC_ANSWER_BUILDER_CELL];
                  });
    [cell configureCellWithThirdPartyObject:self.items[indexPath.row]];
    return [cell heightForCellWithTableWidth:self.tableView.frame.size.width];
}

Eu configuro a célula com meu objeto de dados em tempo real e, em seguida, chamo um método que tenho nele, que calcula a altura da célula com uma determinada largura de tabela (nem sempre posso confiar que o quadro de células está correto inicialmente).

Isso, por sua vez, chama um método de altura, na minha opinião, já que é onde a gravadora mora:

- (CGFloat)heightForCellWithTableWidth:(CGFloat)tableWidth {
    // subtract 38 from the constraint above
    return [self.thirdPartyAnswerView heightForViewWithViewWidth:tableWidth - 38];
}

Esse método determina a altura por descobrir a largura correta do rótulo e, em seguida, fazendo um cálculo:

- (CGFloat)heightForViewWithViewWidth:(CGFloat)viewWidth {
    CGFloat widthForCalc = viewWidth - self.imageFrameLeadingSpaceConstraint.constant - self.thumbnailFrameWidthConstraint.constant - self.titleLabelLeadingSpaceConstraint.constant;
    CGSize size = [self.titleLabel.text sizeWithFont:self.titleLabel.font constrainedToSize:CGSizeMake(widthForCalc, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
    CGFloat returnHeight = self.frame.size.height - self.titleLabel.frame.size.height + size.height;
    CGFloat height = returnHeight < self.frame.size.height ? self.frame.size.height : returnHeight;
    return height;
}

Isso funciona 100% corretamente.

As células são criadas obviamente em cellForRowAtIndexPath e imediatamente configuradas:

if (self.items.count > 0) {
    TCAnswerBuilderCell *cell = [tableView dequeueReusableCellWithIdentifier:TC_ANSWER_BUILDER_CELL forIndexPath:indexPath];
    [cell configureCellWithThirdPartyObject:self.items[indexPath.row]];
    return cell;
}

Na configuração da célula, minha visão é carregada de uma ponta (ela é reutilizada em outro lugar, e é por isso que ela não está diretamente na célula). A célula adiciona da seguinte maneira:

- (void) configureCellWithThirdPartyObject:(TCThirdPartyObject *)object {
    self.detailDisclosureImageView.hidden = NO;
    if (!self.thirdPartyAnswerView) {
        self.thirdPartyAnswerView = [TCThirdPartyAPIHelper thirdPartyAnswerViewForThirdPartyAPIServiceType:object.thirdPartyAPIType];
        self.thirdPartyAnswerView.translatesAutoresizingMaskIntoConstraints = NO;
        [self.contentView addSubview:self.thirdPartyAnswerView];
        [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[_thirdPartyAnswerView]-38-|" options:NSLayoutFormatAlignAllCenterY metrics:nil views:NSDictionaryOfVariableBindings(_thirdPartyAnswerView)]];
    }
    [self.thirdPartyAnswerView configureViewForThirdPartyObject:object forViewStyle:TCThirdPartyAnswerViewStyleSearchCell];
}

Finalmente minha configuração de visão é assim:

- (void) configureViewForThirdPartyObject:(TCTPOPlace *)object forViewStyle:(TCThirdPartyAnswerViewStyle) style {
    self.titleLabel.text = object.name;
    self.addressLabel.text = [NSString stringWithFormat:@"%@, %@, %@", object.address, object.city, object.state];
    self.ratingsLabel.text = [NSString stringWithFormat:@"%d Ratings", object.reviewCount];
    NSString *ratingImageName = [NSString stringWithFormat:@"yelp_star_rating_%.1f.png", object.rating];
    UIImage *ratingsImage = [UIImage imageNamed:ratingImageName];
    if (ratingsImage) {
        self.ratingImageView.image = ratingsImage;
    }
    if (object.imageUrl) {
        [self.thumbnailImageView setImageWithURL:[NSURL URLWithString:object.imageUrl] completed:nil];
    }
}
Uma espécie de solução, mas não entendo porqueMinha subvisualização foi projetada em 320 de largura, mas não possui restrições próprias para larguraA subvisualização foi adicionada à célula, mas com restrições horizontais que se parecem com isso:@"|[_thirdPartyAnswerView]-38-|"A visualização foi configurada imediatamente após ser adicionada à célula, o que significa que o texto para o titleLabel foi definido corretamente.Por qualquer motivo, o texto foi colocado como se a vista tivesse o total de 320 em vez de 282.O rótulo nunca foi atualizado, embora o quadro da subvisualização tenha sido atualizado para 282 e havia restrições no rótulo que o manteriam dimensionados corretamente.Alterar o tamanho da exibição no xib para corrigir o problema, porque o rótulo tem o tamanho certo para começar.

Ainda não estou entendendo por que o rótulo não é reimplantado depois que o tamanho da visualização pai é atualizado quando há restrições de entrada e de saída.

RESOLVIDO

Veja a resposta de Matt abaixo:https://stackoverflow.com/a/15514707/287403

Caso você não leia o comentário, o principal problema é que eu estava sem saberpreferredMaxLayoutWidth via IB ao projetar uma vista em uma largura maior do que seria mostrada (em alguns casos).preferredMaxLayoutWidth é o que é usado para determinar onde o texto é quebrado. Portanto, embora minha view e titleLabel tenham sido redimensionados corretamente,preferredMaxLayoutWidth ainda estava no valor antigo e causando envolvimento em pontos inesperados. Definindo o titleLabel em vez de seu tamanho automático (⌘ = em IB), e atualizando opreferredMaxLayoutWidth dinamicamente emlayoutSubviews antes de chamar super era a chave. Obrigado Matt!

questionAnswers(3)

yourAnswerToTheQuestion