Skip to content

Commit 634ddbf

Browse files
committed
Set preferredMaxLayoutWidth based on an initial layout pass instead of hardcoding it
This method is somewhat less efficient as it requires a second layout pass once the preferredMaxLayoutWidth is set on multi-line labels, however it is much more flexible and generic and can scale to arbitrarily complex layouts that would be very difficult to determine the correct preferredMaxLayoutWidth value manually.
1 parent 66d6c44 commit 634ddbf

3 files changed

Lines changed: 13 additions & 63 deletions

File tree

TableViewCellWithAutoLayout/TableViewController/RJTableViewCell.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626

2727
#import <UIKit/UIKit.h>
2828

29-
#define kLabelHorizontalInsets 20.0f
30-
3129
@interface RJTableViewCell : UITableViewCell
3230

3331
@property (strong, nonatomic) IBOutlet UILabel *titleLabel;

TableViewCellWithAutoLayout/TableViewController/RJTableViewCell.m

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727
#import "RJTableViewCell.h"
2828

29+
#define kLabelHorizontalInsets 20.0f
30+
2931
@interface RJTableViewCell ()
3032

3133
@property (nonatomic, assign) BOOL didSetupConstraints;
@@ -34,11 +36,10 @@ @interface RJTableViewCell ()
3436

3537
@implementation RJTableViewCell
3638

37-
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
39+
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
40+
{
3841
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
3942
if (self) {
40-
// Initialization code
41-
4243
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
4344
[self.titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
4445
[self.titleLabel setLineBreakMode:NSLineBreakByTruncatingTail];
@@ -65,7 +66,8 @@ - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reus
6566
return self;
6667
}
6768

68-
- (void)updateConstraints {
69+
- (void)updateConstraints
70+
{
6971
[super updateConstraints];
7072

7173
if (self.didSetupConstraints) return;

TableViewCellWithAutoLayout/TableViewController/RJTableViewController.m

Lines changed: 7 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -89,19 +89,16 @@ - (void)contentSizeCategoryChanged:(NSNotification *)notification
8989

9090
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
9191
{
92-
// Return the number of sections.
9392
return 1;
9493
}
9594

9695
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
9796
{
98-
// Return the number of rows in the section.
9997
return [self.model.dataSource count];
10098
}
10199

102100
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
103101
{
104-
105102
RJTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
106103

107104
[cell updateFonts];
@@ -119,7 +116,6 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
119116

120117
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
121118
{
122-
123119
RJTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
124120

125121
[cell updateFonts];
@@ -128,13 +124,18 @@ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPa
128124
cell.titleLabel.text = [dataSourceItem valueForKey:@"title"];
129125
cell.bodyLabel.text = [dataSourceItem valueForKey:@"body"];
130126

131-
cell.bodyLabel.preferredMaxLayoutWidth = tableView.bounds.size.width - (kLabelHorizontalInsets * 2.0f);
132-
133127
[cell setNeedsUpdateConstraints];
134128
[cell updateConstraintsIfNeeded];
129+
130+
// Do the initial layout pass of the cell's contentView & subviews
135131
[cell.contentView setNeedsLayout];
136132
[cell.contentView layoutIfNeeded];
137133

134+
// Since we have multi-line labels, set the preferredMaxLayoutWidth now that their width has been determined,
135+
// and then do a second layout pass so they can take on the correct height
136+
cell.bodyLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.bodyLabel.frame);
137+
[cell.contentView layoutIfNeeded];
138+
138139
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
139140

140141
return height;
@@ -145,55 +146,4 @@ - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(
145146
return 500.0f;
146147
}
147148

148-
/*
149-
// Override to support conditional editing of the table view.
150-
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
151-
{
152-
// Return NO if you do not want the specified item to be editable.
153-
return YES;
154-
}
155-
*/
156-
157-
/*
158-
// Override to support editing the table view.
159-
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
160-
{
161-
if (editingStyle == UITableViewCellEditingStyleDelete) {
162-
// Delete the row from the data source
163-
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
164-
}
165-
else if (editingStyle == UITableViewCellEditingStyleInsert) {
166-
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
167-
}
168-
}
169-
*/
170-
171-
/*
172-
// Override to support rearranging the table view.
173-
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
174-
{
175-
}
176-
*/
177-
178-
/*
179-
// Override to support conditional rearranging of the table view.
180-
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
181-
{
182-
// Return NO if you do not want the item to be re-orderable.
183-
return YES;
184-
}
185-
*/
186-
187-
/*
188-
#pragma mark - Navigation
189-
190-
// In a story board-based application, you will often want to do a little preparation before navigation
191-
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
192-
{
193-
// Get the new view controller using [segue destinationViewController].
194-
// Pass the selected object to the new view controller.
195-
}
196-
197-
*/
198-
199149
@end

0 commit comments

Comments
 (0)