请看一下图片。
我有一个带有自定义单元格和2个部分的UITableView。一旦UITableView填充了足够的单元格,它们都无法在屏幕上显示,最后一部分中的最后一个单元格将出现在屏幕的最顶部。在UITableView中甚至看不到单元格,因为它是最后一个单元格,并且它完全出现在屏幕顶部的UITableView外面 。我甚至不知道从哪里开始查看我的代码来解决这个问题。我只创建了几个UITableViews,所以我绝对不是这个bug的所有潜在原因的专家。表是通过IB设置的,初始化代码在viewWillAppear中,尽管设置代码不多。我目前正在阅读UITableView的scrollView,以及contentInset,看看是否可能有这种行为的解释。有谁遇到过这样的错误?我觉得它很独特,可能没有必要梳理我的所有代码来确定。无论如何,我将在下面发布相关代码。谢谢你的帮助!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *uniqueIdentifierForPlayerCell = @"customPlayerCell";
//Initialize PlayerTableViewCell and set it's properties
PlayerTableViewCell *playerCell = nil;
playerCell = (PlayerTableViewCell *)[tableView dequeueReusableCellWithIdentifier:uniqueIdentifierForPlayerCell];
if (playerCell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"PlayerTableViewCell" owner:nil options:nil];
for(id currentObject in topLevelObjects) {
if([currentObject isKindOfClass:[PlayerTableViewCell class]]) {
playerCell = (PlayerTableViewCell *)currentObject;
break;
}
}
}
playerCell.textLabel.opaque = NO;
playerCell.textLabel.textColor = self.textColor;
playerCell.textLabel.font = [UIFont systemFontOfSize:18.0];
playerCell.textLabel.backgroundColor = [UIColor clearColor];
playerCell.selectionStyle = UITableViewCellSelectionStyleNone;
playerCell.accessoryButton.hidden = YES;
playerCell.reorderButton.hidden = YES;
NSString *uniqueIdentifierForAlleyCell = @"customAlleyCell";
//Initialize AlleyTableViewcell and set it's properties
AlleyTableViewCell *alleyCell = nil;
alleyCell = (AlleyTableViewCell *)[tableView dequeueReusableCellWithIdentifier:uniqueIdentifierForAlleyCell];
if (alleyCell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"AlleyTableViewCell" owner:nil options:nil];
for(id currentObject in topLevelObjects) {
if([currentObject isKindOfClass:[AlleyTableViewCell class]]) {
alleyCell = (AlleyTableViewCell *)currentObject;
break;
}
}
}
alleyCell.textLabel.opaque = NO;
alleyCell.textLabel.textColor = self.textColor;
alleyCell.textLabel.font = [UIFont systemFontOfSize:18.0];
alleyCell.textLabel.backgroundColor = [UIColor clearColor];
alleyCell.selectionStyle = UITableViewCellSelectionStyleNone;
alleyCell.accessoryButton.hidden = YES;
alleyCell.deleteButton.hidden = YES;
//Alternate background colors for each section where section 0 is Alley section and section 1 is Player section. Stores the RGB values of the specific background color to the specific cell for future use
if(indexPath.section == 0 && (indexPath.row %2 == 0)) {
alleyCell.contentView.backgroundColor = self.backgroundColor;
alleyCell.isRed = 95.0/255.0;
alleyCell.isGreen = 94.0/255.0;
alleyCell.isBlue = 94.0/255.0;
self.alleyField.backgroundColor = self.backgroundColor;
}
else if(indexPath.section == 0 && (indexPath.row %2 == 1)){
alleyCell.contentView.backgroundColor = self.alternateColor;
alleyCell.isRed = 92.0/255.0;
alleyCell.isGreen = 92.0/255.0;
alleyCell.isBlue = 92.0/255.0;
self.alleyField.backgroundColor = self.alternateColor;
}
else if(indexPath.section == 1 && (indexPath.row %2 == 0)) {
playerCell.contentView.backgroundColor = self.backgroundColor;
playerCell.isRed = 95.0/255.0;
playerCell.isGreen = 94.0/255.0;
playerCell.isBlue = 94.0/255.0;
self.playerField.backgroundColor = self.backgroundColor;
}
else if(indexPath.section == 1 && (indexPath.row %2 == 1)) {
playerCell.contentView.backgroundColor = self.alternateColor;
playerCell.isRed = 92.0/255.0;
playerCell.isGreen = 92.0/255.0;
playerCell.isBlue = 92.0/255.0;
self.playerField.backgroundColor = self.alternateColor;
}
//If Alley array is empty, add alley TextField and return cell
if(indexPath.section == 0) {
if([self.allAlleys count] == 0) {
[alleyCell addSubview:self.alleyField];
self.alleyField.text = nil;
return alleyCell;
}
//Else set the alley name to the nameLabel text and return cell
else {
if(indexPath.row < [self.allAlleys count]) {
alleyCell.textLabel.text = [self.allAlleys objectAtIndex:indexPath.row];
if([alleyCell.textLabel.text isEqualToString: self.selectedAlley]) {
alleyCell.accessoryButton.hidden = NO;
}
else {
alleyCell.accessoryButton.hidden = YES;
}
return alleyCell;
}
//Add alley TextField to the last cell of the UITableView and return cell
else {
[alleyCell addSubview:self.alleyField];
self.alleyField.text = nil;
return alleyCell;
}
}
}
//If Player array is empty, add Player TextField and return cell
else if(indexPath.section == 1) {
if([self.bowlrNames count] == 0) {
[playerCell addSubview:self.playerField];
self.playerField.text = nil;
return playerCell;
}
//Else set the Player name to the nameLabel text and return cell
else {
if(indexPath.row < [self.bowlrNames count]) {
playerCell.textLabel.text = [self.bowlrNames objectAtIndex:indexPath.row];
for(int i = 0; i < [self.selectedBowlrs count]; i++) {
if([playerCell.textLabel.text isEqualToString: [self.selectedBowlrs objectAtIndex:i]]) {
playerCell.accessoryButton.hidden = NO;
playerCell.reorderButton.hidden = NO;
}
}
return playerCell;
}
//Add Player textField to the last cell of the UITableView and return cell
else {
[playerCell addSubview:self.playerField];
self.playerField.text = nil;
return playerCell;
}
}
}
}
//Actions for selecting a row in the UITable
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//If it is in the Alley section
if(indexPath.section == 0) {
//If the selected cell is the same as the last selected cell
if(self.lastIndexPathForAlleyCells && indexPath.row == self.lastIndexPathForAlleyCells.row) {
[tableView beginUpdates];
self.lastIndexPathForAlleyCells = nil;
AlleyTableViewCell *previousCell = (AlleyTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
//[tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:YES];
previousCell.selected = NO;
self.selectedAlley = nil;
previousCell.accessoryButton.hidden = YES;
[tableView endUpdates];
return;
}
//Else the selected cell is not the last selected cell
AlleyTableViewCell *previousCell = (AlleyTableViewCell *)[tableView cellForRowAtIndexPath:self.lastIndexPathForAlleyCells];
previousCell.selected = NO;
previousCell.accessoryButton.hidden = YES;
AlleyTableViewCell *cell = (AlleyTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
cell.selected = YES;
cell.accessoryButton.hidden = NO;
self.selectedAlley = cell.textLabel.text;
self.lastIndexPathForAlleyCells = indexPath;
[self.tableView reloadData];
}
else if(indexPath.section == 1) {
PlayerTableViewCell *cell = (PlayerTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
//If player is not already selected
if([self playerIsSelected:cell.textLabel.text] == NO) {
//Set selected to YES and reveal buttons
cell.selected = YES;
cell.accessoryButton.hidden = NO;
cell.reorderButton.hidden = NO;
//If 8 Players are currently selected, UIAlertView informs user they have reached the limit
if([self.selectedBowlrs count] == 8) {
NSString *message = @"You can only select up to 8 players";
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"Max Players Selected" message:message delegate:self cancelButtonTitle:[self okButtonTitle] otherButtonTitles:nil, nil];
alertView.tag = TAG_FULLGAME;
[alertView show];
}
else {
//Insert name into selectedBowlrs array
[self.selectedBowlrs insertObject:cell.textLabel.text atIndex:0];
//Reorder bowlrNames array
NSString *bowlrName = [self.bowlrNames objectAtIndex:indexPath.row];
[self.bowlrNames removeObjectAtIndex:indexPath.row];
[self.bowlrNames insertObject:bowlrName atIndex:0];
//Move selected row to top of section
[self moveIndexPathToTop:indexPath];
}
}
//Else the player is already selected
else {
//Set selected to NO and hide buttons
cell.selected = NO;
cell.accessoryButton.hidden = YES;
cell.reorderButton.hidden = YES;
[self.selectedBowlrs removeObject:cell.textLabel.text];
[self.bowlrNames removeObject:cell.textLabel.text];
[self.bowlrNames insertObject:cell.textLabel.text atIndex:[self.selectedBowlrs count]];
[self moveIndexPathToMiddle:indexPath];
for(int i = 0; i < [self.selectedBowlrs count]; i++) {
NSLog(@"%@", [self.selectedBowlrs objectAtIndex:i]);
}
}
}
[self performSelector:@selector(reloadData) withObject:nil afterDelay:.25];
}
//Returns the number of rows for each section
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
switch (section) {
//For Alley section
case 0:
//If the array is empty, return 1 row for the Alley Textfield
if([self.allAlleys count] == 0)
return 1;
//Else return the number of elements in the array + 1 for the Alley Textfield
else
return [self.allAlleys count] + 1;
break;
//For Player section
case 1:{
//If the array is empty, return 1 row for the Player Textfield
if([self.bowlrNames count] == 0)
return 1;
//Else return the number of elements in the array + 1 for the Player Textfield
else
return [self.bowlrNames count] + 1;
break;
}
default:
break;
}
return 0;
}
//Set up appearance for section headers
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.tableView.bounds.size.width, 25.0)];
UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectZero];
CGFloat isRed = 84.0/255.0;
CGFloat isGreen = 84.0/255.0;
CGFloat isBlue = 84.0/255.0;
self.headerColor = [[UIColor alloc]initWithRed:isRed green:isGreen blue:isBlue alpha:0.5];
headerLabel.backgroundColor = self.headerColor;
headerLabel.opaque = NO;
headerLabel.textColor = self.textColor;
headerLabel.highlightedTextColor = [UIColor whiteColor];
headerLabel.font = [UIFont systemFontOfSize:18.0];
headerLabel.frame = CGRectMake(0.0, 0.0, self.tableView.bounds.size.width, 25.0);
if (section == 0) {
[headerView setBackgroundColor:self.backgroundColor];
headerLabel.text = @"Alley";
[headerView addSubview:headerLabel];
}
else {
[headerView setBackgroundColor:self.backgroundColor];
headerLabel.text = @"Bowlr";
[headerView addSubview:headerLabel];
}
return headerView;
}
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
//Used to delete row of UITable
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
self.indexPathForEditing = indexPath;
if(editingStyle == UITableViewCellEditingStyleDelete) {
//For Alley section
if(indexPath.section == 0) {
//Set up UIAlertView
NSString *message = @"Are you sure?";
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"Delete Alley?" message:message delegate:self cancelButtonTitle:[self cancelButtonTitle] otherButtonTitles:[self deleteButtonTitle], nil];
alertView.tag = TAG_Alley;
[alertView show];
}
//For Player section
else if(indexPath.section == 1) {
//Set up UIAlertView
NSString *message = @"All information for this Bowlr will be deleted";
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"Delete Bowlr?" message:message delegate:self cancelButtonTitle:[self cancelButtonTitle] otherButtonTitles:[self deleteButtonTitle], nil];
alertView.tag = TAG_Player;
[alertView show];
}
}
[self performSelector:@selector(reloadData) withObject:nil afterDelay:.25];
}
答案 0 :(得分:0)
好的,我认为你需要记住两件基本的事情。
(1)您绝不能将某些内容添加到单元格作为子视图。仅将其添加到单元格的contentView
。此代码错误:[alleyCell addSubview:self.alleyField];
(2)这些细胞正在重复使用。您可能有100行但只有10个单元格,在用户滚动时不断重复使用。因此,您必须从空状态完全设置每个单元格,如果它不是空状态,则需要将其置于空状态。如果您通过cellForRowAtIndexPath
一次向单元格添加文本字段,则必须记住通过cellForRowAtIndexPath
删除每个其他行中的文本字段,或者文本字段可以显示在其他行中,因为另一行可能会重复使用同一个细胞。
(另见本书本节末尾的讨论:http://www.apeth.com/iOSBook/ch21.html#_the_three_big_questions它讨论了忘记细胞被重复使用的简单结果。)
另外,我几乎不需要添加框架。你正在添加一个子视图,但我不知道它的框架是什么。使用正确(意味着错误)的帧值,该子视图可能出现在单元格之外。另外,你使用不同高度的细胞吗?如果是这样,请记住,因为细胞正在重复使用,它的高度可能会改变。因此,自动调整行为可能会导致帧发生变化。