核心数据对象在不同的​​tableView部分

我有一个tableView与可扩展/可折叠部分和固定部分标题,我想要维护。 这是这样做的代码:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 6; } + (NSString*) titleForHeaderForSection:(int) section { switch (section) { case 0 : return @"Overdue"; case 1 : return @"Today"; case 2 : return @"Tomorrow"; case 3 : return @"Upcoming"; case 4 : return @"Someday"; case 5 : return @"Completed"; // default : return [NSString stringWithFormat:@"Section no. %i",section + 1]; } } 

目前,我正在使用以下代码填充行:

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { switch (section) { case 2 : return 1; case 3 : return 30; default : return 8; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; } // Configure the cell. switch (indexPath.row) { case 0 : cell.textLabel.text = @"First Cell"; break; case 1 : cell.textLabel.text = @"Second Cell"; break; case 2 : cell.textLabel.text = @"Third Cell"; break; case 3 : cell.textLabel.text = @"Fourth Cell"; break; case 4 : cell.textLabel.text = @"Fifth Cell"; break; case 5 : cell.textLabel.text = @"Sixth Cell"; break; case 6 : cell.textLabel.text = @"Seventh Cell"; break; case 7 : cell.textLabel.text = @"Eighth Cell"; break; default : cell.textLabel.text = [NSString stringWithFormat:@"Cell %i",indexPath.row + 1]; } //cell.detailTextLabel.text = ...; return cell; } 

但我想填充核心数据实体的行,这是我的NSFetchedResultsController:

 - (NSFetchedResultsController *)fetchedResultsController { if (_fetchedResultsController != nil) { return _fetchedResultsController; } NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"ToDoItem" inManagedObjectContext:self.managedObjectContext]; [fetchRequest setEntity:entity]; NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"tdText" ascending:NO]; [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]]; [fetchRequest setFetchBatchSize:20]; NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"]; self.fetchedResultsController = theFetchedResultsController; _fetchedResultsController.delegate = self; return _fetchedResultsController; } 

核心数据实体是'ToDoItem',我最终想要的是每个对象都出现在tableView的右边部分。 我需要你的帮助和build议。


为了让我的问题更清楚些,我将创build一个名为tdDate的属性,并且此属性应该是过滤关键字,以决定在哪个部分显示对象。 考虑到当前date的对象将显示在今天的TODAY部分下,明天它应该出现在OVERDUE部分下面…

一个很好的方法是在您的ToDoItem (例如state )中添加一个新属性,您可以将它作为sectionNameKeyPath使用。

我会尝试用一个简单的例子来解释。

想想一个列出食物的Food实体。 这个实体有一个name和一个category 。 例如

 Apple, Fruit Banana, Fruit Potato, Vegetable Salad, Vegetable 

如果您将category用作sectionNameKeyPath您将会find两个部分。 一个包含属于Fruit类的食物,另一个包含Vegetable

如果在您的实体中使用state属性(为了简单起见,这是一个string,但您可以使用数字并使用映射将每个数字映射到string值),情况也是如此。 我想这是正确的,因为每个项目将有一个完成状态。 另外,通过这种方法,与每个state相关的值可以dynamic地改变 。 这应该是模型的一部分而不是控制器的一部分。 因此, state可以承担这些可能的价值之一: @"Overdue"@"Today"@"Tomorrow"@"Upcoming"@"Someday"@"Completed"

作为一个重要的说明(请参阅Apple doc)

如果控制器生成段,则使用数组中的第一个sorting描述符将对象分组为段; 其键必须与sectionNameKeyPath相同,或者使用键的相对顺序必须与使用sectionNameKeyPath的顺序相匹配。

我可以想到至less有两个合理的策略。 一个是做一些单独的提取,每个类别一个。 每个获取请求将被赋予一个谓词,以select那些到期date和状态适合于每个类别的ToDoItem对象。 例如,“Today”的提取请求将select截止date为当前date且状态不完整的项目; 对“已完成”的请求将忽略date并select所有状态已完成的项目。

另一个策略是一次获取所有的项目,并在获取之后自己对它们进行分类。 这可能在概念上更简单,您仍然可以使用NSPredicate对对象进行分类。 例如,您可以使用NSSet的-objectsPassingTest:方法或NSArray的-filteredArrayUsingPredicate:方法。

花一些时间阅读使用谓词和获取对象 。

您应该能够通过计算ToDoItem应该出现在正确部分(即0 =逾期,1 =今天,2 =明天)的瞬态属性(例如itemState)对获取的结果进行分组。

 [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"itemState" cacheName:@"Root"]; 

在您的托pipe对象中,实现itemState以返回项目的计算状态:

 - (NSString *)itemState { // logic to return @"Overdue", @"Today", etc.. based on whatever logic makes sense in your app // see this on how to implement transient properties http://davemeehan.com/technology/objective-c/core-data-transient-properties-on-nsmanagedobject 

}

然后你可以继续使用你的FRC来实现你的UITableViewControllerDataSource方法:

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects]; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return [self.fetchedResultsController sections].count; } 

…等…