UITableView单元格奇怪地消失

从马尔科队来找你

我们正在讨论一个令人难以置信的奇怪问题,我们的表格视图单元格通常显示如下:

在这里输入图像说明

看起来像这样:

在这里输入图像说明

经过审查,这个错误似乎发生在你把iPhone置于睡眠状态,然后重新打开应用程序并进入放置tableview的uiviewcontroller。 不知何故,这使得cellForRowAtIndexPath不再被调用,即使委托和数据源仍然设置为self。 我们的部分和行号仍然正常,我们可以向下滚动tableview。 但是因为cellForRowAtIndexPath没有被调用,tableviewcells是隐藏的。

在这里输入图像说明

这是我们的tableview设置(我从这个巨大的文件中剔除了与tableview无关的东西:

// // SPHomeViewController.m // Spek @interface SPHomeViewController () <UITableViewDataSource, UITableViewDelegate, MKMapViewDelegate, SPCreationViewDelegate, UIAlertViewDelegate, CLLocationManagerDelegate> @property (nonatomic, strong) UITableView* tableView; @property (nonatomic, strong) NSMutableArray* tableDatasource; @property (nonatomic, strong) NSMutableArray* datasource; @property (nonatomic, strong) NSMutableArray* friendsDatasource; @property (nonatomic, strong) UISegmentedControl* userFilterSegment; @property (nonatomic) BOOL isLoadingData; @end @implementation SPHomeViewController @synthesize datasource = _datasource; @synthesize friendsDatasource = _friendsDatasource; @synthesize tableDatasource = _tableDatasource; - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; //[[SPLocationManager locationManager] startUpdatingLocationForSig]; [self setNeedsStatusBarAppearanceUpdate]; self.view.backgroundColor = [UIColor colorWithRed:230.0f/255.0f green:230.0f/255.0f blue:230.0f/255.0f alpha:1.0]; self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - kTopBarHeight)]; self.tableView.separatorColor = [UIColor clearColor]; self.tableView.backgroundColor = [UIColor clearColor]; self.tableView.delegate = self; self.tableView.dataSource = self; [self.view addSubview:self.tableView]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. if (self.creationView.center.y > self.view.frame.size.height) { self.creationView = nil; } NSLog(@"Mem warning"); } //**************************************** //**************************************** #pragma mark - UITableViewDelegate/DataSource //**************************************** //**************************************** - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"INDEX PATH ROW: %d AND SECTION: %d", indexPath.row, indexPath.section); if (indexPath.section == 0) { UITableViewCell* cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"SPMapCellSpace"]; cell.backgroundColor = [UIColor clearColor]; cell.backgroundView = [[UIView alloc] init]; cell.selectedBackgroundView = [[UIView alloc] init]; return cell; } else if (indexPath.section == self.tableDatasource.count + 1) { UITableViewCell* cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"SPBottomCellSpace"]; cell.backgroundColor = [UIColor clearColor]; cell.backgroundView = [[UIView alloc] init]; cell.selectedBackgroundView = [[UIView alloc] init]; return cell; } SPMark* mark = self.tableDatasource[indexPath.section - 1]; NSString* reuseId = [SPHomeViewController cellIdentifierFromData:mark]; SPTableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuseId]; if (cell == nil) { cell = [SPTableViewCell cellFromMark:mark reuseID:reuseId]; [cell updateView:YES]; } [cell addDataToCell:mark]; if (indexPath.section >= self.tableDatasource.count - 2 && !self.isLoadingData && self.pageNumber != -1) { self.fetchNextPage = YES; // When the scrollview stops it will load more data if available. } return cell; } - (unsigned int)getPageNumber { return (self.userFilterSegment.selectedSegmentIndex == 0) ? self.pageNumber : self.friendsPageNumber; } - (void)setCurrentPageNumber:(unsigned int)page { if (self.userFilterSegment.selectedSegmentIndex == 0) { self.pageNumber = page; } else { self.friendsPageNumber = page; } } - (void)incrementCurrentPageNumber { if (self.userFilterSegment.selectedSegmentIndex == 0) { self.pageNumber++; } else { self.friendsPageNumber++; } } // Every cell has a section header so this should be equal to the number of speks returned from the server - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { NSLog(@"section count is: %d",self.tableDatasource.count + 2 ); return self.tableDatasource.count + 2; // Add two because the mapview needs to go on the top and extra spacing at the bottom. } // There is a section for every cell, so there is only one cell per section - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 1; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 0) { return kMapHeight+2; } else if (indexPath.section == self.tableDatasource.count + 1) { return kExtraSpaceBelowHomeView; } SPMark* mark = self.tableDatasource[indexPath.section - 1]; return [SPTableViewCell cellHeightForMark:mark]; } - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 0 || indexPath.section == self.tableDatasource.count + 1) { cell.backgroundColor = [UIColor clearColor]; } } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 0 || indexPath.section == self.tableDatasource.count + 1) return; SPMark* mark = self.datasource[indexPath.section - 1 ]; SPMarkViewController* markVC = [SPMarkViewController withMark:mark]; [markVC displayData]; [self.navigationController pushViewController:markVC animated:YES]; } -(void)reloadTableview { [self.tableView setDelegate:self]; dispatch_async(dispatch_get_main_queue(), ^{ [self.tableView reloadData]; [self.tableView setNeedsDisplay]; }); } - (void)showNoItems { if (self.tableDatasource.count == 0 && self.accuracyBad == NO) { self.opaqueIcon.hidden = NO; self.noItems.hidden = NO; self.beTheFirst.hidden = NO; self.downArrow.hidden = NO; self.noItemsBackround.hidden = NO; [self.view bringSubviewToFront:self.noItemsBackround]; [self.view bringSubviewToFront:self.downArrow]; [self.view bringSubviewToFront:self.beTheFirst]; [self.view bringSubviewToFront:self.noItems]; [self.view bringSubviewToFront:self.opaqueIcon]; } } - (void)showTableView { if (self.tableDatasource.count != 0) { self.noItems.hidden = YES; self.beTheFirst.hidden = YES; self.downArrow.hidden = YES; self.noItemsBackround.hidden = YES; self.opaqueIcon.hidden = YES; [self.view sendSubviewToBack:self.noItemsBackround]; [self.view sendSubviewToBack:self.downArrow]; [self.view sendSubviewToBack:self.beTheFirst]; [self.view sendSubviewToBack:self.noItems]; [self.view sendSubviewToBack:self.opaqueIcon]; } } //**************************************** //**************************************** #pragma mark - Setters/Getters //**************************************** //**************************************** - (NSMutableArray*)datasource { if (!_datasource) { _datasource = [NSMutableArray array]; if (!self.firstLoad) { [self loadDataForPagination:NO]; } } return _datasource; } - (NSMutableArray*)friendsDatasource { if (!_friendsDatasource) { _friendsDatasource = [NSMutableArray array]; if (!self.firstLoad) { [self loadDataForPagination:NO]; } } return _friendsDatasource; } - (NSMutableArray*)tableDatasource { if (!_tableDatasource) { _tableDatasource = (self.userFilterSegment.selectedSegmentIndex == 0) ? self.datasource : self.friendsDatasource; } return _tableDatasource; } - (SPCreationView*)creationView { if (!_creationView) { UIView* window = [SPUtils getAppDelegate].window; CGSize viewSize = window.frame.size; CGRect startFrame = CGRectMake(0, viewSize.height, [SPUtils screenWidth], [SPUtils screenHeight]); _creationView = [SPCreationView creationView:startFrame delegate:self]; [window insertSubview:_creationView belowSubview:self.creationButton]; _creationView.frame = startFrame; } return _creationView; } - (void)setTableDatasource:(NSMutableArray *)tableDatasource { _tableDatasource = tableDatasource; [self preFetchImages]; dispatch_async(dispatch_get_main_queue(), ^{ if(_tableDatasource == nil || _tableDatasource.count == 0) { [self showNoItems]; } else { [self showTableView]; } [self reloadTableview]; }); } - (void)setDatasource:(NSMutableArray *)datasource { _datasource = datasource; } - (void)setFriendsDatasource:(NSMutableArray *)friendsDatasource { _friendsDatasource = friendsDatasource; } @end 

最后,如果你认为这与我们的委托有关,那么我们就不会触摸那里的视图控制器,所以我不知道这可能是一个问题。 也许是内存问题或后台线程问题?

这是很多代码,这可能是你的自定义SPTableViewCell类的问题,甚至不是你提供的。

为了加快速度,当你重现问题进入debugging器并转储视图层次结构。 你可以通过在你的视图控制器上调用[self.view recursiveDescription]来实现。 这将导致整个子视图层次被打印到控制台,这将让你看到你的单元格应该 – 但不是 – 正在显示。 如果没有给你任何喜悦,请在这里发布输出。

但是,更奇怪的是,tableview仍然存在,它不是子视图问题,因为你仍然可以滚动:

它可能仍然是一个子视图问题 – tableview从单独的调用中获取单元格的高度,所以独立于单元格本身。 尝试打印出层次结构,看看发生了什么。

问题是太多的后台线程一次进行。 当我们停止尝试预取图像时,问题就消失了。