0

I have an assignment in which I have to load the following items in a table view

  1. Image
  2. Title
  3. Description

The footer view is a simple horizontal black coloured rule of about 5 points.

But only the image is visible, but not the title and the description. Somehow the other views are obscured by the image view.

My Custom TableView Cell in Storyboard

My custom tableview cell implementation

#import <UIKit/UIKit.h>

@interface MeowFestTableViewCell : UITableViewCell
@property (strong, nonatomic) IBOutlet UILabel *titleLabel;
@property (strong, nonatomic) IBOutlet UILabel *descriptionLabel;
@property (strong, nonatomic) IBOutlet UIImageView *imageView;

@end

and the implementation

#import "MeowFestTableViewCell.h"

@implementation MeowFestTableViewCell

- (void)awakeFromNib {
    [super awakeFromNib];
    // Initialization code
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
    }
    return self;
}

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

    if (self) {

    }
    return self;
}

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

    // Configure the view for the selected state
}

@end

My view controller

#import "MeowFestViewController.h"
#import "MeowFestTableViewCell.h"

@interface MeowFestViewController ()

@property (nonatomic, assign) NSInteger page;

@property (nonatomic, strong) NSMutableArray* feedItems;

@property (nonatomic, strong) NSMutableData* responseData;

@property (nonatomic, assign) CGPoint currentOffset;
@property (strong, nonatomic) IBOutlet UITableView *tableView;

@end

@implementation MeowFestViewController

-(void) awakeFromNib {
    [super awakeFromNib];
}

-(void) loadView {
    [super loadView];
    // Force load.
    UIView* view = self.view;
    self.page = 0;
    self.currentOffset = CGPointZero;

}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.tableView setDelegate:self];
    [self.tableView setDataSource:self];
    self.meowFestProtocolDelegate = self;
    [self.meowFestProtocolDelegate getTheFeed:self.page];

}

#pragma mark - MeowFestProtocol

-(void) getTheFeed:(NSInteger) page {
    NSString* url =
        [NSString stringWithFormat:@"https://chex-triplebyte.herokuapp.com/api/cats?page=%d", self.page];
    NSURL* nsUrl = [[NSURL alloc] initWithString:url];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:nsUrl];
    [request setHTTPMethod:@"GET"];

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request
                                            completionHandler:
        ^(NSData *data, NSURLResponse *response, NSError *error) {
                self.feedItems = [NSJSONSerialization JSONObjectWithData: data
                    options: NSJSONReadingMutableContainers error: &error];
                [self.tableView reloadData];
            dispatch_semaphore_signal(semaphore);
        }];

    [task resume];
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

}



#pragma Table Arguments.
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.feedItems count] + 1; // (10 items  + 1 button)
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
    if (indexPath.row == 10) {
        return 50.0f;
    }
    return 300.0f;
}

-(UIView*) tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
    UIView* footerView =
        [[UIView alloc] initWithFrame:CGRectMake(
            0, 0, CGRectGetWidth(self.view.bounds), 5)];
    [footerView setBackgroundColor:[UIColor blackColor]];
    return footerView;
}

-(CGFloat)
tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
    return 5.0f;
}
-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.row != 10) {
        MeowFestTableViewCell* tableViewCell = (MeowFestTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"meowFestCell"];
        if (tableViewCell == nil) {
            tableViewCell = [[MeowFestTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"meowFestCell"];
        }

        NSDictionary* dict = (NSDictionary*) [self.feedItems objectAtIndex:(self.page * 10 + indexPath.row)];
        // Initialise the data.
        tableViewCell.titleLabel.text = (NSString*) [dict objectForKey:@"title"];
        [tableViewCell.titleLabel sizeToFit];
        tableViewCell.descriptionLabel.text = (NSString*) [dict objectForKey:@"description"];
        [tableViewCell.descriptionLabel sizeToFit];
        UIImage* catImage =
        [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[dict objectForKey:@"image_url"]]]];

        tableViewCell.imageView.image = catImage;
        return tableViewCell;
    } else {
        UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"loadMoreCell"];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"loadMoreCell"];
        }
        cell.backgroundColor = [UIColor colorWithRed:0.50 green:0.00 blue:0.50 alpha:1.0];
        return cell;
    }
}

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // rows in section 0 should not be selectable
    if (indexPath.row == 10) {
        return indexPath;
    }
    return nil;
}

- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
    CGPoint offset = scrollView.contentOffset;
    CGSize size = scrollView.contentSize;
    if (abs(size.height - offset.y) < 10) {
        self.currentOffset = offset;
    } else if (offset.y < self.currentOffset.y) {
        if (offset.y == 0) {
            self.page = 0;
            self.currentOffset = CGPointZero;
        }
    }
}

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row == [self.feedItems count]) {
        [self.meowFestProtocolDelegate getTheFeed:(self.page + 1)];
        self.page = self.page + 1;
        [self.tableView reloadData];
    }

}



/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

The output in the simulator is given belowSimulator Output and Analysis of Views

UPDATE

I tried to add missing constraints as per @vadian's suggestion, but that option is disabled for me.

Add Constraints disabled and All subviews selected

UPDATE # 2: @vadian's Setting the height constraints of both the UILabels works, but is there a way to not have to hard code the height of the UILabels? I am getting the content by making an API call, so I have no control over the returned text. The text can be as long as possible. I have already set the number of lines = 0 while the line break mode = Word Break.

halfer
  • 19,824
  • 17
  • 99
  • 186
Kartik
  • 2,541
  • 2
  • 37
  • 59
  • give bottom constraint to description label and you will get error then resolve error through xcode correction . – KKRocks Aug 03 '17 at 11:11
  • Hi, I have already defined the constraint for the description label. Right now, superview.bottom = descriptonLabel.bottom + 35 and descriptionlabel.top = titleLabel.bottom + 35 – Kartik Aug 03 '17 at 11:47
  • then why it displayed constraints warning. – KKRocks Aug 03 '17 at 11:48
  • Use heightForRow_atIndexPath delegate method of tableView. And return the height of row whatever you want to have, but make sure you must have correctly added the constraints to the labels (top, leading trailing) is mandatory ( you can also use width and centre horizontally in container instead of leading and trailing). – Amit Kumar Aug 03 '17 at 11:52
  • I already have defined a function called "heightForRowAtIndexPath" – Kartik Aug 03 '17 at 11:53
  • 1
    Use vertical content hugging and content compression instead of the height constraints. (See my answer.) – Moshe Aug 03 '17 at 12:05

2 Answers2

1
  • Click into the table view cell (outside the image view and labels)
  • Press ⌘A
  • Choose from the popup menu at bottom right or menu bar menu Resolve Auto Layout Issues

enter image description here

vadian
  • 274,689
  • 30
  • 353
  • 361
1

To set this up, you want to add vertical spacing constraints to the labels.

  1. Add a vertical spacing constraint between the image and the top label.
  2. Add a vertical spacing constraint between the two labels.
  3. Add a vertical spacing constraint between the bottom label and the bottom of the containing view.
  4. Now, on each of the labels, set the vertical content compression resistance to 1000, and the vertical content hugging to 1000. This should allow the labels to autosize, and fit their contents.
  5. On your table view (in code) set the estimatedRowHeight to some value that you think your cell will take on, and set the rowHeight to UITableViewAutomaticDimension. This will tell the table view to base the row height on the height of the cell. (Which is in turn based on the heights of all of the things inside of it. See this answer for more information.)

More On Content Size

Check it this article by Hector Matos which explains the concepts of content hugging priority and content compression resistance pretty nicely. Among other thing, the article contains this useful graphic, from a tweet:

Compression Resistance vs Content Hugginh

Moshe
  • 57,511
  • 78
  • 272
  • 425
  • Hi, the content hugging and compression worked, but I am getting wierd image alignment issues. Can you please advise? See the images in the post https://imgur.com/a/zaNvP – Kartik Aug 04 '17 at 09:37