Ios 将tabBarController切换到包含多个单元格的tableView时出现延迟

Ios 将tabBarController切换到包含多个单元格的tableView时出现延迟,ios,objective-c,uitableview,uitabbarcontroller,Ios,Objective C,Uitableview,Uitabbarcontroller,我的应用程序基于tabBarController,有两个选项卡 我在后台加载第二个选项卡的数据,而应用程序在选项卡1启动,因此用户在单击选项卡2时无需等待 我的问题是:如果我提前加载了数据,并且在属于表2的tableView的单元格中有很多数据要显示,那么切换到表2是很慢的。如果没有太多的细胞可以显示,那么它一点也不滞后 我想这是因为生成单元格很耗时,所以当单元格太多时视图会被阻止。我如何优化它 重要这段代码还没有在XCode中测试过,但包含一些来自实际项目的部分 CellView类可以作为Ni

我的应用程序基于tabBarController,有两个选项卡

我在后台加载第二个选项卡的数据,而应用程序在选项卡1启动,因此用户在单击选项卡2时无需等待

我的问题是:如果我提前加载了数据,并且在属于表2的tableView的单元格中有很多数据要显示,那么切换到表2是很慢的。如果没有太多的细胞可以显示,那么它一点也不滞后


我想这是因为生成单元格很耗时,所以当单元格太多时视图会被阻止。我如何优化它

重要这段代码还没有在XCode中测试过,但包含一些来自实际项目的部分

CellView
类可以作为Nib创建,甚至可以使用
ServicesHelper.m
中的
calculateCellHeight
方法手动创建。在这两种情况下,必须在要放置resize
detailTextLabel
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