Ios 将tabBarController切换到包含多个单元格的tableView时出现延迟
我的应用程序基于tabBarController,有两个选项卡 我在后台加载第二个选项卡的数据,而应用程序在选项卡1启动,因此用户在单击选项卡2时无需等待 我的问题是:如果我提前加载了数据,并且在属于表2的tableView的单元格中有很多数据要显示,那么切换到表2是很慢的。如果没有太多的细胞可以显示,那么它一点也不滞后Ios 将tabBarController切换到包含多个单元格的tableView时出现延迟,ios,objective-c,uitableview,uitabbarcontroller,Ios,Objective C,Uitableview,Uitabbarcontroller,我的应用程序基于tabBarController,有两个选项卡 我在后台加载第二个选项卡的数据,而应用程序在选项卡1启动,因此用户在单击选项卡2时无需等待 我的问题是:如果我提前加载了数据,并且在属于表2的tableView的单元格中有很多数据要显示,那么切换到表2是很慢的。如果没有太多的细胞可以显示,那么它一点也不滞后 我想这是因为生成单元格很耗时,所以当单元格太多时视图会被阻止。我如何优化它 重要这段代码还没有在XCode中测试过,但包含一些来自实际项目的部分 CellView类可以作为Ni
我想这是因为生成单元格很耗时,所以当单元格太多时视图会被阻止。我如何优化它 重要这段代码还没有在XCode中测试过,但包含一些来自实际项目的部分
CellView
类可以作为Nib创建,甚至可以使用ServicesHelper.m
中的calculateCellHeight
方法手动创建。在这两种情况下,必须在要放置resizedetailTextLabel
UILabel
代码的位置执行LayoutSubView
方法。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};
}
- (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;
}
TableView.h
@property (nonatomic, strong) NSMutableArray *arrayOfTexts;
@property (nonatomic, strong) NSMutableDictionary *dictOfHeights;
TableView.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};
}
- (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;
}
-(空)预计算高度{
如果(nil==self.dictOfHeights)self.dictOfHeights=[NSMutableDictionary new];
CGRect screenRect=[[UIScreen mainScreen]边界];
//两屏高度
CGFloat maxHeight=最大值(screenRect.size.width,screenRect.size.height)*2;
CGFloat总高度=0;
cgf的高度;
景观高度;
NSDictionary*高度;
for(int i=0;i最大高度)中断;
}
}
-(CGFloat)tableView:(UITableView*)表视图行高度索引路径:(NSIndexPath*)索引路径
{
if(self.dictofheight&&self.dictofheight[@(indexPath.row)]){
返回UIDeviceOrientationSportRait([UIDevice currentDevice]。方向)?
[self.dictof权重[@(indexPath.row)][kPortraitHeightKey]floatValue]:
[self.dictof权重[@(indexPath.row)][kLandscapeHeightKey]floatValue];
}否则{
//您可以决定从这里调用特定行的calculateCellHeight,或者也可以为即将到来的单元格集计算行高
//@todo:
}
返回cgumin;
}
请附上您的代码以便我们提供帮助:如果您使用uitableviewcell Dequeue,生成单元格的时间不是什么大问题。哦,是的,我的单元格的高度是根据数据的内容大小动态计算的,我想真正耗时的是计算高度。无论如何,我相信这是一个普遍的问题,当有很多细胞,所以我不知道我的代码,你想看到的部分。例如,如何在后台、tableview数据源或其他任何地方加载数据?这样,您就不需要一次计算所有单元格的高度,只需计算适合前两个屏幕的单元格的高度(在循环时,您始终可以使用screenRect检查总高度),然后稍后以某种方式更新单元格高度容器。@teamnorge,你的建议很有道理!你能回答这个问题并告诉我细节吗?谢谢:D