UITableViewCell systemLayoutSizeFittingSize: returning 0 on iOS 7

4k views Asked by At

I have a UITableViewCell with a UIImage fixed at the left top corner, and a label at its right:

    -(UITableViewCell*) adCellFromTableView:(UITableView*)tableView
{
    //Build the text
    NSString* adText = NSLocalizedString(@"MyFamily_fremiumAd", nil);
    NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString:adText];

    NSUInteger newLineLocation = [adText rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]].location;

    //Set the first line in orange
    NSDictionary* firstLineAttributes = @{NSFontAttributeName:[UIFont systemFontOfSize:15],
                                          NSForegroundColorAttributeName:ORANGE};
    [attrString addAttributes:firstLineAttributes range:NSMakeRange(0, newLineLocation)];
    //Set other lines in white
    NSDictionary* otherLinesAttributes = @{NSFontAttributeName:[UIFont systemFontOfSize:11],
                                           NSForegroundColorAttributeName:[UIColor whiteColor]};
    [attrString addAttributes:otherLinesAttributes range:NSMakeRange(newLineLocation, adText.length - newLineLocation)];

    //Get the cell
    if (!adCell)
    {
        adCell = [tableUsers dequeueReusableCellWithIdentifier:@"fremiumAd"];
    }

    //Set the text
    UILabel* label = (UILabel*)[adCell viewWithTag:1];
    label.attributedText = attrString;

    //Hide the separator
    adCell.separatorInset = UIEdgeInsetsMake(0, adCell.bounds.size.width, 0, 0);

    return adCell;
}


-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [self adCellFromTableView:tableView];

            //Make sure the cell's bounds are the same as tableview's before calculating the height
            //This is important when we calculate height after a UI rotation.
            cell.bounds = CGRectMake(0, 0, tableView.bounds.size.width, 0);
            NSLog(@"cell.bounds: %@",NSStringFromCGRect(cell.bounds));
            [cell setNeedsLayout];
            [cell layoutIfNeeded];

            CGSize fittingSize = [cell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
            NSLog(@"fittingSize: %@",NSStringFromCGSize(fittingSize));
            return fittingSize.height;
}

When I run the app on iOS 7.1 simulator, systemLayoutSizeFittingSize always return 0:

cell.bounds: {{0, 0}, {320, 0}}

fittingSize: {0,0}

When I run the app on iOS 8.1 simulator, systemLayoutSizeFittingSize return a correct value:

cell.bounds: {{0, 0}, {320, 0}}

fittingSize: {320, 154.5}

What am I missing?

Edit: I kinda fixed the problem using [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; instead of [cell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

But this is just an half fix: when I rotate while the cell is visible, the size calculation is OK. But when I scroll the cell out of the screen, rotate the UI and then scroll back to the cell, the height calculation is wrong again in iOS 7.1

Here are logs before rotating from landscape to portrait:

tableView bounds: {{0, 0}, {569, 227}}

cell.bounds : {{0, 0}, {569,0}}

cell.contentView: {{0, 0}, {569, 0}}

fittingSize: {559, 162}

Here are logs after rotating from landscape to portrait:

tableView bounds: {{0, 249}, {321, 463}}

cell.bounds : {{0, 0}, {321,0}}

cell.contentView: {{0, 0}, {321, 0}}

fittingSize: {559, 162}

As you can see, the size calculation is the same, no matter what the cell/cell.contentView width is.

This result in a oversized cell when rotating from portrait to landscape, and an undersized cell when rotating from landscape to portrait.

1

There are 1 answers

0
董嘉伟 On

You're right that use cell.contentView instead of cell in systemLayoutSizeFittingSize: method. Using Auto Layout,all custom subviews should only be added into cell's contentView,as well as constraints. Then Auto Layout cells work well as your expected.

As your second question,I have solved similar problem. Insert following code in your -(void) didRotateFromInterfaceOrientation :(UIInterfaceOrientation)fromInterfaceOrientation method perhaps can help you solve this problem.

-(void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation)fromInterfaceOrientation
{
    // Update the layout for the new orientation
    //Maybe you should change it to your own tableview
      [self updateViewConstraints]; 
      [self.view layoutIfNeeded];
     // other any code 
    ...

}