如何使用第一个字符作为节名称

nev*_*ing 38 iphone cocoa-touch core-data objective-c uitableview

我正在使用Core Data作为表格视图,我想使用每个结果的第一个字母作为节标题(所以我可以在侧面获得节索引).有没有办法用关键路径做到这一点?像下面的东西,我name.firstLetter用作sectionNameKeyPath(不幸的是,这不起作用).

我是否必须手动抓取每个结果的第一个字母并创建我的部分?是否更好地放入一个新属性来保存第一个字母并将其用作sectionNameKeyPath

NSFetchedResultsController *aFetchedResultsController = 
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
            managedObjectContext:managedObjectContext
            sectionNameKeyPath:@"name.firstLetter"
            cacheName:@"Root"];
Run Code Online (Sandbox Code Playgroud)

谢谢.

**编辑:**我不确定它是否有所作为,但我的结果是日语,按片假名排序.我想用这些片假名作为部分索引.

ger*_*ry3 79

您应该只将"name"作为sectionNameKeyPath传递.请参阅"Core Data支持带索引的UITableView"问题的答案.

更新
该解决方案仅在您只关心拥有快速索引标题滚动条时才有效.在这种情况下,您不会显示节标题.请参阅下面的示例代码.

否则,我同意refulgentis,即瞬态属性是最佳解决方案.此外,在创建NSFetchedResultsController时,sectionNameKeyPath具有此限制:

如果此密钥路径与fetchRequest中第一个排序描述符指定的密钥路径不同,则它们必须生成相同的相对排序.例如,fetchRequest中的第一个排序描述符可能指定持久属性的键; sectionNameKeyPath可以指定从persistent属性派生的transient属性的键.

使用NSFetchedResultsController的Boilerplate UITableViewDataSource实现:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [[fetchedResultsController sections] count];
}

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    return [fetchedResultsController sectionIndexTitles];
}

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
    return [fetchedResultsController sectionForSectionIndexTitle:title atIndex:index];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];
}

// Don't implement this since each "name" is its own section:
//- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
//    id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
//    return [sectionInfo name];
//}
Run Code Online (Sandbox Code Playgroud)

更新2

对于新的"uppercaseFirstLetterOfName"瞬态属性,将新的字符串属性添加到模型中的适用实体,并选中"瞬态"框.

有几种方法可以实现getter.如果要生成/创建子类,则可以将其添加到子类的实现(.m)文件中.

否则,您可以在NSManagedObject上创建一个类别(我把它放在我的视图控制器的实现文件的顶部,但您可以在它自己的正确的头和实现文件之间拆分):

@interface NSManagedObject (FirstLetter)
- (NSString *)uppercaseFirstLetterOfName;
@end

@implementation NSManagedObject (FirstLetter)
- (NSString *)uppercaseFirstLetterOfName {
    [self willAccessValueForKey:@"uppercaseFirstLetterOfName"];
    NSString *aString = [[self valueForKey:@"name"] uppercaseString];

    // support UTF-16:
    NSString *stringToReturn = [aString substringWithRange:[aString rangeOfComposedCharacterSequenceAtIndex:0]];

    // OR no UTF-16 support:
    //NSString *stringToReturn = [aString substringToIndex:1];

    [self didAccessValueForKey:@"uppercaseFirstLetterOfName"];
    return stringToReturn;
}
@end
Run Code Online (Sandbox Code Playgroud)

此外,在此版本中,不要忘记将'uppercaseFirstLetterOfName'作为sectionNameKeyPath传递:

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext
sectionNameKeyPath:@"uppercaseFirstLetterOfName" // this key defines the sections
cacheName:@"Root"];
Run Code Online (Sandbox Code Playgroud)

并且,要tableView:titleForHeaderInSection:在UITableViewDataSource实现中取消注释:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo name];
}
Run Code Online (Sandbox Code Playgroud)

  • 我做这项工作遇到了最大的麻烦.我的解决方案是`[NSSortDescriptor sortDescriptorWithKey:@"name"升序:YES选择器:@selector(caseInsensitiveCompare :)]`而不是`[NSSortDescriptor sortDescriptorWithKey:@"name"ascending:YES]`因为我的一个对象开始了小写字符. (6认同)

ref*_*tis 11

可能有更优雅的方式来做到这一点,但我最近遇到了同样的问题,并提出了这个解决方案.

首先,我在我正在索引的对象上定义了一个名为firstLetterOfName的瞬态属性,并将getter写入该对象的.m文件中.前

- (NSString *)uppercaseFirstLetterOfName {
    [self willAccessValueForKey:@"uppercaseFirstLetterOfName"];
    NSString *stringToReturn = [[self.name uppercaseString] substringToIndex:1];
    [self didAccessValueForKey:@"uppercaseFirstLetterOfName"];
    return stringToReturn;
}
Run Code Online (Sandbox Code Playgroud)

接下来,我设置我的获取请求/实体以使用此属性.

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Object" inManagedObjectContext:dataContext];
[request setEntity:entity];
[NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[request setSortDescriptors:sortDescriptors];
Run Code Online (Sandbox Code Playgroud)

注意事项,没有任何结果:小心NSFetchedResultsController - 它还没有完全被烘焙,但恕我直言,除了文档中列出的简单案例之外的任何情况,你可能会以"老式"的方式做得更好.