Matt Welson Matt Welson - 4 months ago 36
iOS Question

UITableView cell width on iOS 8 stuck at 320pt

I am currently trying to create a simple UITableView with custom cells without using storyboard.

I'm getting an issue on the iPhone 6 simulator where the table view has a width of 375 (as it should), but the cells inside are getting a width of 320.

The number 320 is nowhere to be found in the project as I am not hard coding it. When I am setting the background colour of the cell, it extends the full width of 375, but I need to align an image to the right, which only aligns 320 across as shown in the photo below.

image of weird tableviewcell sizing

I'm not sure if it's because I'm missing constraints or if there's a bug. Any help is appreciated, thanks!

Code to set up table:

- (TBMessageViewCell *)getMessageCellforTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath
{

static NSString *cellIdentifier = @"MessageCell";
TBMessageViewCell *cell = (TBMessageViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[TBMessageViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
[cell createSubviews];
}

// Set the new message and refresh
[cell setMessage:self.viewModel.messages[indexPath.row]];
[cell populateSubviews];
cell.backgroundColor = [UIColor blueColor];

NSLog(@"cell Width: %f", cell.contentView.frame.size.width);

return cell;
}


Complete TBMessageViewCell:

@implementation TBMessageViewCell

const CGFloat MARGIN = 10.0f;
const CGFloat AVATAR_SIZE = 40.0f;

-(id)initWithStyle:(UITableViewCellStyle *)style reuseIdentifier:(NSString *)reuseIdentifier
{
if(self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier]){
}

// Sets background and selected background color
self.backgroundColor = [UIColor clearColor];
UIView *selectionColor = [[UIView alloc] init];
selectionColor.backgroundColor = [UIColor clearColor];
self.selectedBackgroundView = selectionColor;

return self;
}

- (void)populateSubviews
{
// Set the message body
[self.messageBodyLabel setText:self.message.body];
[self.messageBodyLabel setTextAlignment:NSTextAlignmentRight];
CGRect bodyFrame = CGRectMake(MARGIN, MARGIN, self.frame.size.width - (AVATAR_SIZE + (MARGIN * 3)), self.frame.size.height);
// Calculates the expected frame size based on the font and dimensions of the label
// FLT_MAX simply means no constraint in height
CGSize maximumLabelSize = CGSizeMake(bodyFrame.size.width, FLT_MAX);
CGRect textRect = [self.message.body boundingRectWithSize:maximumLabelSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:self.messageBodyLabel.font}
context:nil];
bodyFrame.size.height = textRect.size.height;

// Setup the new avatar frame (Right aligned)
CGRect avatarFrame = CGRectMake(bodyFrame.size.width + (MARGIN * 2), MARGIN, AVATAR_SIZE, AVATAR_SIZE);

// Align to the LEFT side for current user's messages
if ([[TBConfig userID] isEqualToString:self.message.user.userID]) {
// Set avatar to left if it's me
avatarFrame.origin.x = MARGIN;
bodyFrame.origin.x = AVATAR_SIZE + (MARGIN * 2);
[self.messageBodyLabel setTextAlignment:NSTextAlignmentLeft];
}

self.avatar.frame = avatarFrame;
self.avatar.layer.cornerRadius = self.avatar.frame.size.width/2;
self.messageBodyLabel.frame = bodyFrame;

// Set the new cell height on the main Cell
CGFloat cellHeight = MAX(bodyFrame.size.height, self.frame.size.height) + MARGIN;
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, cellHeight);

// Set the new Profile avatar
if (![self.avatar.profileID isEqualToString:self.message.user.facebookID]) {
[self.avatar setProfileID:nil];
[self.avatar setProfileID:self.message.user.facebookID];
}
}

- (void)createSubviews
{
self.messageBodyLabel = [[UILabel alloc] init];
self.messageBodyLabel.textColor = [UIColor whiteColor];
self.messageBodyLabel.lineBreakMode = NSLineBreakByWordWrapping;
self.messageBodyLabel.numberOfLines = 0;
[self addSubview:self.messageBodyLabel];

// Creates the avatar
self.avatar = [[FBProfilePictureView alloc] init];
[self.avatar setPictureCropping:FBProfilePictureCroppingSquare];
[self addSubview:self.avatar];
}

Answer

You're printing the size of the cell before it has been added to the display — before it has been sized. Who are you imagining will have sized the cell? Where do you think ot is supposed to get the table view width from? It doesn't even know which table view it's going to be handed to yet.

The cells will be given an appropriate frame when added to the display.

EDIT: oh, and you probably don't want that cellIdentifier to be static. You probably wanted *const.

Comments