IOS 10.3 Label height calculation problem (UITableView+FDTemplateLayoutCell)

1. Preface

Today, there are user feedback that 10.3 of the system, some text shows incomplete, affecting the formal user, where dare I snub?. A quick update of the mobile phone system to test, found that there is a problem, and the problem is caused by UITableView+FDTemplateLayoutCell, the calculation of highly inaccurate caused.

2. problem discovery

After the test found after Xib or nib to create cell and UITableView+FDTemplateLayoutCell pull constraint height calculation problems arise, Masonry no problem with the use of UITableView+FDTemplateLayoutCell (at least for me is not a problem, of course, if you have problems you can see I list solution, I believe there is for you)

3. solving problems

After Gogle found so far few people have mentioned this problem (do you have not found or you have no problem, of course, there may be no use of UITableView+FDTemplateLayoutCell, UITableView+FDTemplateLayoutCell and Masonry) in issues issues there are a lot of problems mentioned in this. The reason, as if iOS 10.3 will add a width, a high constraint (Looks like iOS has two additional constraints there for width/height), the constraints on the Autolayout has a new way of calculation.

4. list the ways to solve the problem

1. set label’s preferredMaxLayoutWidth

This method pro test is possible, but there is a problem, nib created cell, many do not know how much this value is in the end, that is, can not know a cell, a cell settings! At least I don’t want to. Oh, God, dozens of cell! Of course, some people may be the easy way, arbitrarily set a bar, label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width – 80 so you will find the test is really a newline, but really? Label’s line feed is based on this preferredMaxLayoutWidth, which is similar to the method of calculating text height

- (CGRect) boundingRectWithSize: (CGSize) size options: (NSStringDrawingOptions) options attributes: (nullable NSDictionary< NSString id> * *, attributes context: (nullable) NSStringDrawingContext * context) NS_AVAILABLE (10_11, 7_0)

As this method is to set the width of the size size label can display wide, if not of course to calculate the height will not, if the small to calculate the height is high, to the large calculation height is low

2. plus [cell layoutIfNeeded]

Because sometimes I find the first label display is no problem, but the refresh is not good, so I want to refresh before reflashing is highly constrained, so that you can know the maximum width limit of label, of course, I also don’t want to be so cell treatment so do some processing in UITableView+FDTemplateLayoutCell.

- (CGFloat) fd_heightForCellWithIdentifier: (NSString * identifier) (configuration: (void ^) (ID)) {if (configuration! Identifier) {return 0;} / / Fetch a cached template cell for `identifier`. UITableViewCell *cell = [self fd_templateCellForReuseIdentifier:identifier]; Manually calls to ensure consistent behavior / with actual cells (that are displayed on screen). [cell prepareForReuse] and provide content for; / / Customize our template cell. if (configuration) {configuration} (cell); CGFloat contentViewWidth = CGRectGetWidth (self.frame); / / If a cell has accessory view or system accessory type, its content view's width is smaller cell's by some fixed / / than values. if (cell.accessoryView) {contentViewWidth = 16 + CGRectGetWidth (cell.accessoryView.frame);} else {static CGFloat systemAccessoryWidths[] = {[UITableViewCellAccessoryNone] = 0, [UITableViewCellAccessoryDisclosureIndicator] = 34, [UITableViewCellAccessoryDetailDisclosureButton] = 68, UITableViewCellAccessoryCheckmark] = 40, [UITableViewCellAccessoryDetailButton] = 48, contentViewWidth = systemAccessoryWidths[cell.accessoryType];}}; CGSize fittingSize = CGSizeZero; / / If auto layout enabled, cell's contentView must have some constraints. BOOL autoLayoutEnabled = cell.contentView.constraints.count > 0; & & cell.fd_enforceFrameLayout; if! (autoLayoutEnabled a hard width) {/ / Add constraint to make dynamic conte NT views (like labels) expand vertically instead growing in a / / of horizontally, flow-layout manner. if (IOS_VERSION > 10.2) {[cell layoutIfNeeded]}; NSLayoutConstraint *tempWidthConstraint = [NSLayoutConstraint constraintWithItem: cell.contentView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:contentViewWidth]; [cell.contentView addConstraint:tempWidthConstraint]; Auto layout engine does its math / / fit TingSize = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; [cell.contentView removeConstraint:tempWidthConstraint];} else {/ / If not using auto layout, you have to override "-sizeThatFits:" to provide a fitting size by yourself. is the same method / / This used in iOS8 self-sizing cell's implementation. fitting height should not / / Note: include separator view. SEL selector (sizeThatFits:) = @selector; BOOL = inherited [cell! IsMemberOfClass: UITableViewCell.class] BOOL; overrided = [cell.class instanceMethodForSelector:selector] = [UITableViewCell instanceMethodForSelector:selector]! If (inherited; & & overrided {NSAssert (NO!), "Customized cell must override '@ -sizeThatFits:'method if not using auto layout. ");} fittingSize [cell = sizeThatFits:CGSizeMake (contentViewWidth, 0)];} / / Add 1px extra space for separator line if needed, simulating default UITableViewCell. if (self.separatorStyle! = UITableViewCellSeparatorStyleNone) {fittingSize.height = 1 / [UIScreen mainScreen].scale;} if {[self (autoLayoutEnabled) fd_debugLog:[NSString stringWithFormat:@ calculate using auto layout -"% @, @ (fittingSize.height) ";} else {[self fd_debugLog:[NSString stringWithFormat:@ calculate using frame layout (fittingSize.height),"% @ @ "}; return fittingSize.height;}

* focus on here,

IOS 10.3 Label height calculation problem (UITableView+FDTemplateLayoutCell)
1.png

Of course, if this can meet you is very good, but I can not meet the project, this is the height of the problem can be solved completely created by NIB cell, but the pure code with Masonry restriction but there is a problem, but can not wrap, so this method is not suitable for me, I think this way. He continue to look down

3. give cell.contentView plus or left restraint

Here I understand, since Xcode automatically added to our “left and right binding” problem, then I don’t use it, I add it myself

IOS 10.3 Label height calculation problem (UITableView+FDTemplateLayoutCell)
2.png

Replace layoutIfNeeded in the same place, replaced with left behind with the priorityLow constraint, remember, this is to avoid cell manual and constraint conflict, so as to meet the nib cell skills can also satisfy the pure cell code, without a cell a cell change. So far, this problem has been solved perfectly. (my problem is solved, have you solved it? Welcome to discuss the message, the Mavericks passing by, do not like not to spray!

What, you’re too lazy to knock me off?! Well, I can’t stand you anymore

- (CGFloat) fd_heightForCellWithIdentifier: (NSString * identifier) (configuration: (void ^) (ID)) {if (configuration! Identifier) {return 0;} / / Fetch a cached template cell for `identifier`. UITableViewCell *cell = [self fd_templateCellForReuseIdentifier:identifier]; Manually calls to ensure consistent behavior / with actual cells (that are displayed on screen). [cell prepareForReuse] and provide content for; / / Customize our template cell. if (configuration) {configuration} (cell); CGFloat contentViewWidth = CGRectGetWidth (self.frame); / / If a cell has accessory view or system accessory type, its content view's width is smaller cell's by some fixed / / than values. if (cell.accessoryView) {contentViewWidth = 16 + CGRectGetWidth (cell.accessoryView.frame);} else {static CGFloat systemAccessoryWidths[] = {[UITableViewCellAccessoryNone] = 0, [UITableViewCellAccessoryDisclosureIndicator] = 34, [UITableViewCellAccessoryDetailDisclosureButton] = 68, UITableViewCellAccessoryCheckmark] = 40, [UITableViewCellAccessoryDetailButton] = 48, contentViewWidth = systemAccessoryWidths[cell.accessoryType];}}; CGSize fittingSize = CGSizeZero; / / If auto layout enabled, cell's contentView must have some constraints. BOOL autoLayoutEnabled cell.contentView.constraints.count > = 0; & & cell.fd_enforceFrameLayout; if! (autoLayoutEnabled a hard width) {/ / Add constraint to make dynamic content views (like labels) expand vertically instead growing in a / / of horizontally, flow-layout manner. if (IOS_VERSION > 10.2) {[cell.contentView mas_makeConstraints:^ (MASConstraintMaker *make) {make.left.mas_equalTo (0) (.PriorityLow); make.right.mas_equalTo (0) (.PriorityLow);}]; *tempWidthConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView NSLayoutConstraint} attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute: NSLayoutAttributeNotAnAttribute multiplier:1.0 Constant:contentViewWidth]; [cell.contentView addConstraint:tempWidthConstraint]; layout engine does its math / Auto fittingSize = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; [cell.contentView removeConstraint: tempWidthConstraint];} else {/ / If not using auto layout, you have to override "-sizeThatFits:" to provide a fitting size by yourself. is the same method / / This used in iOS8 self-sizing cell's implementation. fitting height should not include / / Note: separator view. SEL selector = @selector (sizeThatFits:); BOOL inherited = [cell isMemberOfClass:UITableViewCell.class]; BOOL overrided! = [cell.class instanceMethodForSelector:selector] [UITableViewCell! = instanceMethodForSelector:selector] (inherited & if; & overrided {NSAssert (NO!), "Customized cell must override @'-sizeThatFits:'method if not using auto layout.");} fittingSize [cell sizeThatFits: = CGSizeMake (contentViewWidth, 0)];} / / Add 1px extra space for separator line if needed, simulating default UITableViewCell. if (self.separatorStyle! = UITableViewCellSeparatorStyleNone) {fittingSize.height = 1 / [UIScreen mainScreen].Scale;} if {[self (autoLayoutEnabled) fd_debugLog:[NSString stringWithFormat:@ calculate using auto layout -% @, @ (fittingSize.height)} else {[self "; fd_debugLog:[NSString stringWithFormat:@" calculate using frame layout - fittingSize. (% @, @ Height return fittingSize.height ");};}

If you are looking for other versions of their own contrast, and if you are the latest version, look at the following picture

IOS 10.3 Label height calculation problem (UITableView+FDTemplateLayoutCell)
22.png

Method

IOS 10.3 Label height calculation problem (UITableView+FDTemplateLayoutCell)
33.png

Location

IOS 10.3 Label height calculation problem (UITableView+FDTemplateLayoutCell)
44.png

Keguan walking, love like.