我的应用基于tabBarController并有2个标签。
当应用程序在选项卡1上启动时,我在后台加载第二个选项卡的数据,因此用户在单击选项卡2时无需等待。
我的问题是:如果我提前加载数据并且有很多数据要显示在属于选项卡2的tableView的单元格中,那么切换到选项卡2会很困难。如果要显示的单元格不多,那么它不是总的来说很迟钝。
我想这是因为生成单元格非常耗时,因此当单元格太多时视图会被阻止。我该如何优化?
答案 0 :(得分:0)
重要!此代码尚未在XCode中进行测试,但包含来自实际项目的部分内容。
CellView
类可以作为Nib创建,甚至可以使用calculateCellHeight
中的ServicesHelper.m
方法手动创建。在这两种情况下,必须在要调整大小layoutSubviews
detailTextLabel
代码的位置实施UILabel
方法。 CellView
标签字体和颜色必须与calculateCellHeight
方法中使用的相同。
<强> ServicesHelper.m 强>
#define FontRegular(fontSize) [UIFont fontWithName:@"HelveticaNeue" size:fontSize]
// the height of fixed part of the cell, fixed height UILabel + some padding
#define kFixedPartCellHeight 20
#define kLeftPaddingWidth 20
#define kLandscapeHeightKey @"landscapeKey"
#define kPortraitHeight @"portraitKey"
+ (NSDictionary *) calculateCellHeight: (NSString *) text {
// dynamic height label
UILabel *detailTextLabel = [UILabel new];
UIFont *mainFont = FontRegular(14.0);
// specifying font and colour to be used inside cell is important to get precise frame rect
[detailTextLabel setFont: mainFont];
[detailTextLabel setTextColor:[UIColor blackColor]];
detailTextLabel.lineBreakMode = NSLineBreakByWordWrapping;
detailTextLabel.numberOfLines = 0;
[textLabel setBackgroundColor: [UIColor clearColor]];
[detailTextLabel setBackgroundColor: [UIColor clearColor]];
// get the width of the cell for both orientations
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat landscapeWidth = MAX (screenRect.size.width, screenRect.size.height);
CGFloat portraitWidth = MIN (screenRect.size.width, screenRect.size.height);
// kLeftPaddingWidth - is just a white space left and right to the UILabel inside cell
// we set the UILabel width with maximum possible height, then set text and shrink it using sizeToFit to get the exact size
detailTextLabel.frame = CGRectMake (0, 0 , landscapeWidth - kLeftPaddingWidth * 2, CGFLOAT_MAX);
textLabel.frame = detailTextLabel.frame;
detailTextLabel.text = text;
[detailTextLabel sizeToFit];
CGFloat landscapeHeight = detailTextLabel.frame.size.height + kFixedPartCellHeight;
detailTextLabel.frame = CGRectMake (0, 0 , portraitWidth - kLeftPaddingWidth * 2, CGFLOAT_MAX);
textLabel.frame = detailTextLabel.frame;
detailTextLabel.text = text;
[detailTextLabel sizeToFit];
CGFloat portraitHeight = detailTextLabel.frame.size.height + kFixedPartCellHeight;
return @{kLandscapeHeightKey: landscapeHeight, kPortraitHeightKey: portraitHeight};
}
<强> TableView.h 强>
@property (nonatomic, strong) NSMutableArray *arrayOfTexts;
@property (nonatomic, strong) NSMutableDictionary *dictOfHeights;
<强> TableView.m 强>
- (void) precalculateHeight {
if (nil == self.dictOfHeights) self.dictOfHeights = [NSMutableDictionary new];
CGRect screenRect = [[UIScreen mainScreen] bounds];
// height of two screens
CGFloat maxHeight = MAX (screenRect.size.width, screenRect.size.height) * 2;
CGFloat totalHeight = 0;
CGFloat portraitHeight;
CGFloat landscapeHeight;
NSDictionary *dictHeights;
for (int i = 0; i < self.arrayOfTexts.count; i++ ) {
dictHeights = [ServicesHelper calculateCellHeight: arrayOfTexts[i]];
portraitHeight = [dictHeights[kPortraitHeightKey] floatValue];
[self.dictOfHeights setValue: dictHeights forKey:@(i)];
totalHeight += portraitHeight;
if (totalHeight > maxHeight) break;
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.dictOfHeights && self.dictOfHeights[@(indexPath.row)]) {
return UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation) ?
[self.dictOfHeights[@(indexPath.row)][kPortraitHeightKey] floatValue] :
[self.dictOfHeights[@(indexPath.row)][kLandscapeHeightKey] floatValue];
} else {
// you decide, call calculateCellHeight for particular row, right from here, or also calculate rows height for the coming set of cells
// @todo:
}
return CGFLOAT_MIN;
}