我有一个带有可扩展/可折叠部分和固定部分标题的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的右边部分内。我需要你的帮助和建议。
为了使我的问题更加清晰,我将创建一个名为tdDate的属性,此属性应该是过滤键,以决定在哪个部分显示对象。考虑到具有当前日期的对象今天将出现在今天的部分下,明天它应出现在OVERDUE部分...
答案 0 :(得分:1)
我能想到至少两种合理的策略。一种是进行多次单独的提取,每种类别一次。每个获取请求都将被赋予一个谓词,该谓词选择那些其到期日期和状态适合每个类别的ToDoItem
个对象。例如,“今天”的获取请求将选择到期日为当前日期且状态不完整的项目; “已完成”的请求将忽略该日期并选择状态已完成的所有项目。
另一种策略是一次获取所有项目,并在获取后自行对其进行分类。这可能在概念上更简单,您仍然可以使用NSPredicate对对象进行分类。例如,您可以使用NSSet的-objectsPassingTest:
方法或NSArray的-filteredArrayUsingPredicate:
方法。
花些时间阅读using predicates和fetching objects。
答案 1 :(得分:1)
一种很好的方法是在ToDoItem
中添加一个新属性(例如state
),您可以将sectionNameKeyPath
用作NSFetchedResultsController
。
我将尝试用一个简单的例子来解释。
想一个列出食物的Food
实体。此实体包含name
和category
。 e.g。
Apple, Fruit
Banana, Fruit
Potato, Vegetable
Salad, Vegetable
如果您使用category
作为sectionNameKeyPath
,则会找到两个部分。一个将包含属于Fruit
类别的食物,另一个将包含Vegetable
类别的食物。
如果在您的实体中使用state
属性,则同样适用(为简单起见,它是一个字符串,但您可以使用数字并使用地图将每个数字映射到字符串值)。我想这是正确的,因为每个项目都有一个完成状态。 此外,通过此方法,与每个state
相关联的值可以动态更改。这应该是模型的一部分而不是控制器的一部分。
因此,state
可以假定其中一个可能的值:@"Overdue"
,@"Today"
,@"Tomorrow"
,@"Upcoming"
,@"Someday"
,@"Completed"
作为一个重要的注释(参见Apple doc)
如果控制器生成节,则第一个排序描述符在 数组用于将对象分组为多个部分;它的关键必须要么 与sectionNameKeyPath或使用它的相对排序相同 key必须与sectionNameKeyPath匹配。
答案 2 :(得分:1)
您应该能够通过瞬态属性(例如itemState)对获取的结果进行分组,该属性计算ToDoItem应该出现的正确部分(即0 =过期,1 =今天,2 =明天)。
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"itemState"
cacheName:@"Root"];
在您的托管对象中,实现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;
}
...等......