iOS:UITableViewController – cellForRowAtIndexPath单元格创build

我知道苹果文档没有指定cellForRowAtIndexPath顺序,即首先它将去0节,索引0; 然后第0节,索引2; 然后第1部分,索引0 ….等等。 我觉得它跳了起来。

什么是更好的方式来完成下面的? 目前我不断收到错误

NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 3 beyond bounds [0 .. 2]' 

错误出现b / c我认为cellForRowAtIndexPath跳转并标记*sectioned = NULL ,所以条件被跳过,并进入一个空数组或超出索引计数通过转到错误的条件。

这里是代码:

 ... declared and synthesized NSManaged *object; @property (strong, nonatomic) NSNumber *sevenDaysSectionFilled; @property (strong, nonatomic) NSNumber *fourteenDaysSectionFilled; @property (strong, nonatomic) NSNumber *thirtyDaysSectionFilled; - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { object = NULL; static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; if (indexPath.section == 0) { if ((SevenDaysArraySectioned == [NSNumber numberWithBool:YES]) && (sevenDaysSectionFilled != [NSNumber numberWithBool:YES])) { object = [pastSevenDayArray objectAtIndex:indexPath.row]; sevenDaysSectionFilled = [NSNumber numberWithBool:YES]; } else if ((fourteenDaysArraySectioned == [NSNumber numberWithBool:YES]) && (fourteenDaysSectionFilled != [NSNumber numberWithBool:YES])) { object = [pastFourteenDaysArray objectAtIndex:indexPath.row]; fourteenDaysSectionFilled = [NSNumber numberWithBool:YES]; } else if ((thirtyDaysArraySectioned == [NSNumber numberWithBool:YES]) && (thirtyDaysSectionFilled != [NSNumber numberWithBool:YES])) { object = [pastThirtyDaysArray objectAtIndex:indexPath.row]; thirtyDaysSectionFilled = [NSNumber numberWithBool:YES]; } else if (indexPath.section == 1) { if ((fourteenDaysArraySectioned == [NSNumber numberWithBool:YES]) && (fourteenDaysSectionFilled != [NSNumber numberWithBool:YES])) { object = [pastFourteenDaysArray objectAtIndex:indexPath.row]; fourteenDaysSectionFilled = [NSNumber numberWithBool:YES]; } else if ((thirtyDaysArraySectioned == [NSNumber numberWithBool:YES]) && (thirtyDaysSectionFilled != [NSNumber numberWithBool:YES])) { object = [pastThirtyDaysArray objectAtIndex:indexPath.row]; thirtyDaysSectionFilled = [NSNumber numberWithBool:YES]; } else if (indexPath.section == 2) { if ((thirtyDaysArraySectioned == [NSNumber numberWithBool:YES]) && (thirtyDaysSectionFilled != [NSNumber numberWithBool:YES])) { object = [pastThirtyDaysArray objectAtIndex:indexPath.row]; thirtyDaysSectionFilled = [NSNumber numberWithBool:YES]; } } NSString *entityName = [[object entity]name]; cell.textLabel.text = [NSString stringWithFormat:@"%@ %i", entityName, [indexPath row]]; object = NULL; return cell; } 

请让我知道是否有更好的方法来完成这一点。 谢谢。

* 编辑

这有点复杂,但这里是:

 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { numberOfSections = 0; if ([pastSevenDayArray count] > 0) numberOfSections++; if ([pastFourteenDaysArray count] > 0) numberOfSections++; if ([pastThirtyDaysArray count] > 0) numberOfSections++; if ([pastSixtyDaysArray count] > 0) numberOfSections++; if ([pastNinteyDaysArray count] > 0) numberOfSections++; if ([pastArray count] > 0) numberOfSections++; [self numberOfCells]; return numberOfSections; } 

numberOfCells

 -(void)numberOfCells { for (int section = 0; section<numberOfSections; section ++) { if (section == 0) { if ([pastSevenDayArray count] > 0) { SevenDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionZeroCellCount = [pastSevenDayArray count]; sectionZeroHeader = sevenDaysSectionLabel; } else if ([pastFourteenDaysArray count] > 0) { fourteenDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionZeroCellCount = [pastFourteenDaysArray count]; sectionZeroHeader = fourteenDaysSectionLabel; } else if ([pastThirtyDaysArray count] > 0) { thirtyDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionZeroCellCount = [pastThirtyDaysArray count]; sectionZeroHeader = thirtyDaysSectionLabel; } else if ([pastSixtyDaysArray count] > 0) { sixtyDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionZeroCellCount = [pastSixtyDaysArray count]; sectionZeroHeader = sixtyDaysSectionLabel; } else if ([pastNinteyDaysArray count] > 0) { ninetyDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionZeroCellCount = [pastNinteyDaysArray count]; sectionZeroHeader = ninetyDaysSectionLabel; } else if ([pastArray count] > 0) { pastArraySectioned = [NSNumber numberWithBool:YES]; sectionZeroCellCount = [pastArray count]; sectionZeroHeader = pastSectionLabel; } } else if (section == 1) { if (([pastFourteenDaysArray count] > 0) && (fourteenDaysArraySectioned != [NSNumber numberWithBool:YES])) { fourteenDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionOneCellCount = [pastFourteenDaysArray count]; sectionOneHeader = fourteenDaysSectionLabel; } else if (([pastThirtyDaysArray count] > 0) && (thirtyDaysArraySectioned != [NSNumber numberWithBool:YES])) { thirtyDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionOneCellCount = [pastThirtyDaysArray count]; sectionOneHeader = thirtyDaysSectionLabel; } else if (([pastSixtyDaysArray count] > 0) && (sixtyDaysArraySectioned != [NSNumber numberWithBool:YES])) { sixtyDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionOneCellCount = [pastSixtyDaysArray count]; sectionOneHeader = sixtyDaysSectionLabel; } else if (([pastNinteyDaysArray count] > 0) && (ninetyDaysArraySectioned != [NSNumber numberWithBool:YES])) { ninetyDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionOneCellCount = [pastNinteyDaysArray count]; sectionOneHeader = ninetyDaysSectionLabel; } else if (([pastArray count] > 0) && (pastArraySectioned != [NSNumber numberWithBool:YES])) { pastArraySectioned = [NSNumber numberWithBool:YES]; sectionOneCellCount = [pastArray count]; sectionOneHeader = pastSectionLabel; } } else if (section ==2) { if (([pastThirtyDaysArray count] > 0) && (thirtyDaysArraySectioned != [NSNumber numberWithBool:YES])) { thirtyDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionTwoCellCount = [pastThirtyDaysArray count]; sectionTwoHeader = thirtyDaysSectionLabel; } else if (([pastSixtyDaysArray count] > 0) && (sixtyDaysArraySectioned != [NSNumber numberWithBool:YES])) { sixtyDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionTwoCellCount = [pastSixtyDaysArray count]; sectionTwoHeader = sixtyDaysSectionLabel; } else if (([pastNinteyDaysArray count] > 0) && (ninetyDaysArraySectioned != [NSNumber numberWithBool:YES])) { ninetyDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionTwoCellCount = [pastNinteyDaysArray count]; sectionTwoHeader = ninetyDaysSectionLabel; } else if (([pastArray count] > 0) && (pastArraySectioned != [NSNumber numberWithBool:YES])) { pastArraySectioned = [NSNumber numberWithBool:YES]; sectionTwoCellCount = [pastArray count]; sectionTwoHeader = pastSectionLabel; } } else if (section ==3) { NSLog(@"Entered Section %i", section); if (([pastSixtyDaysArray count] > 0) && (sixtyDaysArraySectioned != [NSNumber numberWithBool:YES])) { sixtyDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionThreeCellCount = [pastSixtyDaysArray count]; sectionThreeHeader = sixtyDaysSectionLabel; } else if (([pastNinteyDaysArray count] > 0) && (ninetyDaysArraySectioned != [NSNumber numberWithBool:YES])) { ninetyDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionThreeCellCount = [pastNinteyDaysArray count]; sectionThreeHeader = ninetyDaysSectionLabel; } else if (([pastArray count] > 0) && (pastArraySectioned != [NSNumber numberWithBool:YES])) { pastArraySectioned = [NSNumber numberWithBool:YES]; sectionThreeCellCount = [pastArray count]; sectionThreeHeader = pastSectionLabel; } } else if (section ==4) { NSLog(@"Entered Section %i", section); if (([pastNinteyDaysArray count] > 0) && (ninetyDaysArraySectioned != [NSNumber numberWithBool:YES])) { ninetyDaysArraySectioned = [NSNumber numberWithBool:YES]; sectionFourCellCount = [pastNinteyDaysArray count]; sectionFourHeader = ninetyDaysSectionLabel; } else if (([pastArray count] > 0) && (pastArraySectioned != [NSNumber numberWithBool:YES])) { pastArraySectioned = [NSNumber numberWithBool:YES]; sectionFourCellCount = [pastArray count]; sectionFourHeader = pastSectionLabel; } } else if (section ==5) { NSLog(@"Entered Section %i", section); if (([pastArray count] > 0) && (pastArraySectioned != [NSNumber numberWithBool:YES])) { pastArraySectioned = [NSNumber numberWithBool:YES]; sectionFiveCellCount = [pastArray count]; sectionFiveHeader = pastSectionLabel; } } } } 

numberOfRowsInSection

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section == 0) { return sectionZeroCellCount; } else if (section == 1) { return sectionOneCellCount; } else if (section == 2) { return sectionTwoCellCount; } else if (section == 3) { return sectionThreeCellCount; } else if (section == 4) { return sectionFourCellCount; } if (section == 5) { return sectionFiveCellCount; } } 

编辑2

标题:

 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 30.0; } - (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 150)]; UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 3, tableView.bounds.size.width - 10, 25)]; label.backgroundColor = [UIColor clearColor]; [label setFont:[UIFont boldSystemFontOfSize:16]]; label.textColor = [UIColor whiteColor]; if (section == 0) { label.text = sectionZeroHeader; } else if (section == 1) { label.text = sectionOneHeader; } else if (section == 2) { label.text = sectionTwoHeader; } else if (section == 3) { label.text = sectionThreeHeader; } else if (section == 4) { label.text = sectionFourHeader; } else if (section == 5) { label.text = sectionFiveHeader; } [headerView addSubview:label]; return headerView; } 

在各种不同的实例variables中,有很多状态是不需要的。 我们可以使用集合和其他数据结构来构build表应该如何的定义,然后在我们的数据源/委托方法中引用这个定义。

这个视图控制器的基本思想是每个部分都由一个CVSectionModel对象来表示,该对象包含该部分的行数据和部分特定的信息,如标题视图。 在viewDidLoad里面,我们build立了这些部分模型,每当我们完成更新数据的时候,我们都应该重新构build它们。 要尝试不同的数据工作安排,请使用其他testing方法之一将viewDidLoad的调用replace为testCase1

我们维护一系列的剖面模型,只有在有内容显示的情况下才为剖面创build模型。 正如你所看到的,这简化了计算哪些数组以获取行信息,以及每个部分中有多less行。 我们只需要在部分模型中查找要执行的操作,而不是同步几个不同的实例variables。

请注意,这个表格控制器不支持更多精细的内容插入,删除或重新sorting的animation,所以如果需要的话,还需要额外的工作。 它确实支持更新后的常规表重新加载,但是,可以在viewDidLoad后10秒运行的块中看到。

请检查代码并提出任何问题。 这是实现文件,但除了@interface CVViewController: UIViewController @end之外,头文件中没有@interface CVViewController: UIViewController @end

 @interface CVSectionModel : NSObject @property (nonatomic) NSArray *rowModels; @property (nonatomic) NSString *sectionTitle; @property (nonatomic) NSInteger tag; // possibly useful for animations, different behavior on section, etc. @end @implementation CVSectionModel @end @interface CVViewController () <UITableViewDataSource, UITableViewDelegate> @property (weak, nonatomic) IBOutlet UITableView *tableView; @property (nonatomic) NSArray *sectionModels; @property (nonatomic) NSArray *sevenDays; @property (nonatomic) NSArray *fourteenDays; @property (nonatomic) NSArray *thirtyDays; @end @implementation CVViewController - (void)viewDidLoad { [super viewDidLoad]; // In your application, you'll be loading and processing your real data // But here I'm just going to simulate a number of cases with strings for illustration // Call the other methods to try different configurations [self testCase1]; // We call this once on viewDidLoad. You'll also want to call it whenever you update the underlying data, as in the block below [self processSectionData]; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"IDENTIFIER"]; // Demonstrate support for modifying the underlying data and refresh the view. // Uncomment to test it. // double delayInSeconds = 10.0; // dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); // dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ // [self testCase2]; // [self processSectionData]; // [self.tableView reloadData]; // }); } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return [self.sectionModels count]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [((CVSectionModel *)self.sectionModels[section]).rowModels count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"IDENTIFIER"]; // In your app this appears to be an NSManagedObject of some type, here it's just a string NSString *modelForRow = ((CVSectionModel *)self.sectionModels[indexPath.section]).rowModels[indexPath.row]; cell.textLabel.text = modelForRow; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 30.0; } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { NSString *sectionTitle = ((CVSectionModel *)self.sectionModels[section]).sectionTitle; UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 150)]; UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 3, tableView.bounds.size.width - 10, 25)]; label.backgroundColor = [UIColor clearColor]; [label setFont:[UIFont boldSystemFontOfSize:16]]; label.textColor = [UIColor whiteColor]; label.text = sectionTitle; [headerView addSubview:label]; return headerView; } - (void)processSectionData { NSArray *allDayArrays = @[self.sevenDays, self.fourteenDays, self.thirtyDays]; // You won't use hard-coded strings here - use your sevenDaysSectionLabel, etc. variables instead NSArray *labelTitles = @[@"7 days", @"14 days", @"30 days"]; NSMutableArray *mutableSectionModels = [NSMutableArray array]; [allDayArrays enumerateObjectsUsingBlock:^(NSArray *array, NSUInteger index, BOOL *stop) { if ([array count] > 0) { CVSectionModel *sectionModel = [[CVSectionModel alloc] init]; sectionModel.rowModels = array; sectionModel.sectionTitle = labelTitles[index]; sectionModel.tag = index+1; // track this to enable re-ordering in the future [mutableSectionModels addObject:sectionModel]; } }]; // If Animating insertions / deletions will require something more elaborate self.sectionModels = [mutableSectionModels copy]; } // Case 1: // All three populated - (void)testCase1 { self.sevenDays = @[@"sevendayitem1", @"sevendayitem2", @"sevendayitem3", @"sevendayitem4"]; self.fourteenDays = @[@"14day item 1", @"14 day item 2"]; self.thirtyDays = @[@"30 day item 1", @"30 day item 2", @"30 day item 3"]; } // Case 2: // self.fourteenDays is empty - (void)testCase2 { self.sevenDays = @[@"sevendayitem1", @"sevendayitem2", @"sevendayitem3", @"sevendayitem4"]; self.fourteenDays = @[]; self.thirtyDays = @[@"30 day item 1", @"30 day item 2", @"30 day item 3"]; } // Case 3: // self.thirtydays is the only one - (void)testCase3 { self.sevenDays = @[]; self.fourteenDays = @[]; self.thirtyDays = @[@"30 day item 1", @"30 day item 2", @"30 day item 3"]; } @end 

我认为你必须确定你设定的适当

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; 

 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; 

如果你想有多个部分,并在每个部分多行请使用NSDictionary,然后设置键 – >数组值

 NSDictionary *dict = @{@"section1": @[@"obj1", @"obj2"],@"section2": @[@"obj3", @"obj4"]}; NSInteger numberOfSections = [[dict allKeys] count];// return in numberOfSections NSArray *values = [dict valueForKey:@"obj1"];// get appropriate array