3

I have a TableView with 3 UILabel: title, author name and category and a UIImage. All cells should look similar to this layout:

Cell Layout

Correct cell layout:

Proper Label Alignment

When the app starts for some reason some cells have the title UILabel alignment not as it should be:

Incorrect title label alignment

Incorrect title label alignment

After scrolling the TableView a few times, these cells end up with the proper alignment. I'm not quite sure what is causing this.

I have created a Custom TableView Cell class (followed this tutorial)

CustomTableViewCell.h

@interface CustomTableViewCell : UITableViewCell
@property (nonatomic, weak) IBOutlet UIImageView *image;
@property (nonatomic, weak) IBOutlet UILabel *titleLabel;
@property (nonatomic, weak) IBOutlet UILabel *authorLabel;
@property (nonatomic, weak) IBOutlet UILabel *categoryLabel;
@end

CustomTableViewCell.m

@implementation CustomTableViewCell

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

    if (self) {
        // Initialization code
    }
    return self;
}

- (void)awakeFromNib
{
   // Initialization code
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

- (void)layoutSubviews
{
    [super layoutSubviews];
    [self.contentView layoutIfNeeded];
    self.titleLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.titleLabel.frame);
    [self.titleLabel sizeToFit];
    [self.titleLabel setNumberOfLines:0];
}

@end

This is how this class is implemented in the ViewController:

@interface CurrentIssueViewController () {
    CurrentIssueModel *_currentIssueModel;
    Article *_selectedArticle;
}

@end

@implementation CurrentIssueViewController

static NSString *cellIdentifier = @"BasicCell";
UIActivityIndicatorView *activityView;
//@synthesize _feedItems;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];


    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangePreferredContentSize:)name:UIContentSizeCategoryDidChangeNotification object:nil];

    // Create array object and assign it to _feedItems variable
    self._feedItems = [[NSArray alloc] init];

    // Create new HomeModel object and assign it to _homeModel variable
    _currentIssueModel = [[CurrentIssueModel alloc] init];

    // Set this view controller object as the delegate for the home model object
    _currentIssueModel.delegate = self;

    // Call the download items method of the home model object
    [_currentIssueModel downloadItems];
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIContentSizeCategoryDidChangeNotification object:nil];
}

- (void)didChangePreferredContentSize:(NSNotification *)notification
{
    [self.tableView reloadData];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)itemsDownloaded:(NSArray *)items
{
    // This delegate method will get called when the items are finished downloading

    // Set the downloaded items to the array
    self._feedItems = items;

    [activityView stopAnimating];

    // Reload the table view
    [self.tableView reloadData];
}

#pragma mark Table View Delegate Methods

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of feed items (initially 0)
    return self._feedItems.count;
}

/* ================================================== */

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
    [self configureCell:cell forRowAtIndexPath:indexPath];
    return cell;
}

- (void)configureCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([cell isKindOfClass:[CustomTableViewCell class]])
    {
        CustomTableViewCell *textCell = (CustomTableViewCell *)cell;

        Article *article_item = self._feedItems[indexPath.row];

        NSString *fulltitle = article_item.Title;

        if (article_item.Subtitle != nil && article_item.Subtitle.length != 0) {
            fulltitle = [fulltitle stringByAppendingString:@": "];
            fulltitle = [fulltitle stringByAppendingString:article_item.Subtitle];
        }
        textCell.titleLabel.text = fulltitle;

        if ([article_item.Author isEqualToString:@"accountant"]) {
            textCell.authorLabel.text = @"";
        }
        else {
            textCell.authorLabel.text = article_item.Author;
        }

        textCell.categoryLabel.text = article_item.Cat_Name;

        textCell.titleLabel.numberOfLines = 0;
        textCell.titleLabel.font = [UIFont fontWithName:@"Arial" size:12.0f];

        textCell.authorLabel.font = [UIFont fontWithName:@"Arial" size:10.0f];
        textCell.categoryLabel.font = [UIFont fontWithName:@"Arial" size:10.0f];
        textCell.categoryLabel.textAlignment = NSTextAlignmentRight;

        NSURL *url;

        if ([article_item.ImageUrl length] != 0) {
            url = [NSURL URLWithString:article_item.ImageUrl];
        }
        else {
            url = [NSURL URLWithString:@"imageurl"];
        }

        [textCell.image sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"default_image.jpg"]];
    }
}

- (CustomTableViewCell *)prototypeCell
{
    if (!_prototypeCell)
    {
        _prototypeCell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    }
    return _prototypeCell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    [self configureCell:self.prototypeCell forRowAtIndexPath:indexPath];

    self.prototypeCell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(self.tableView.bounds), CGRectGetHeight(self.prototypeCell.bounds));

    [self.prototypeCell layoutIfNeeded];

    CGSize size = [self.prototypeCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    return size.height+1;
}

/* ================================================== */

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Set selected article to var
    _selectedArticle = self._feedItems[indexPath.row];
    [self performSegueWithIdentifier:@"detailSegue" sender:self];

}

#pragma mark Segue

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Get reference to the destination view controller
    ArticleViewController *articleVC = segue.destinationViewController;

    // Set the property to the selected article so when the view for
    // detail view controller loads, it can access that property to get the feeditem obj
    articleVC.selectedArticle = _selectedArticle;
}

@end

I guess it's something to do with forRowAtIndexPath but I can't really figure out what's the issue.

Update:

I noticed that there is another problem with the title UILabel. Whenever you select a cell, view the article in another ViewController and go back to the UITableView the title labels are positioned in the Center Left rather than Top Left. Once you scroll again the title labels adjust to the proper position.

j.grima
  • 1,831
  • 3
  • 23
  • 45
  • check my answer in this http://stackoverflow.com/questions/22104792/ios-customizing-tableviewcell-initializing-custom-cell/22111294#22111294 and use ` - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath` method and init custom cell as per that answer and do the following may be it will helps you – Mohit Aug 26 '14 at 13:22
  • thanks for your comment...I am already using `cellForRowAtIndexPath`, I've updated my question with that function. I'll try out what you suggested. – j.grima Aug 26 '14 at 13:33
  • then try to put all code of forRowAtIndexPath to cellForRowAtIndexPath method as par my that answer. – Mohit Aug 26 '14 at 13:36
  • Same thing happens to some cells – j.grima Aug 26 '14 at 13:51
  • 3
    You should add some constraints to your labels. That's exactly what constraints are used for – angerboy Aug 26 '14 at 15:18
  • Yep thanks for that, had to look into more detail on constraints to see why this were not looking as they should. This post helped a lot: http://www.raywenderlich.com/73602/dynamic-table-view-cell-height-auto-layout – j.grima Aug 27 '14 at 11:57

1 Answers1

1

You have auto layout selected for the NIB/Storyboard but have not added any constraints to your cells. Add layout constraints to your cells. There is a great answer here that explains it in some details:

Community
  • 1
  • 1
Rog
  • 17,070
  • 9
  • 50
  • 73
  • Thanks for this, constraints were not properly set. This helped me realise what was wrong: http://www.raywenderlich.com/73602/dynamic-table-view-cell-height-auto-layout, your link as well. Thanks again. – j.grima Aug 27 '14 at 11:59