与UILocalizedIndexedCollat​​ion

与UILocalizedIndexedCollat​​ion

本文介绍了NSFetchedResultsController 与UILocalizedIndexedCollat​​ion的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用具有混合语言数据的 FRC,并希望有一个部分索引.

I am trying to use a FRC with mixed language data and want to have a section index.

从文档看来,您应该能够覆盖 FRC 的

It seems like from the documentation you should be able to override the FRC's

- (NSString *)sectionIndexTitleForSectionName:(NSString *)sectionName
- (NSArray *)sectionIndexTitles

然后使用 UILocalizedIndexedCollat​​ion 来获得本地化索引和部分.但遗憾的是,这不起作用,也不是打算使用的:(

and then use the UILocalizedIndexedCollation to have a localized index and sections. But sadly this does not work and is not what is intended to be used :(

是否有人能够将 FRC 与 UILocalizedIndexedCollat​​ion 一起使用,或者我们是否被迫使用示例 UITableView + UILocalizedIndexedCollat​​ion 示例中提到的手动排序方法(示例代码包含在我得到这个工作的地方).

Has anyone been able to use a FRC with UILocalizedIndexedCollation or are we forced to use the manual sorting method mentioned in the example UITableView + UILocalizedIndexedCollation example (example code included where I got this working).

使用以下属性

@property (nonatomic, assign) UILocalizedIndexedCollation *collation;
@property (nonatomic, assign) NSMutableArray *collatedSections;

和代码:

- (UILocalizedIndexedCollation *)collation
{
    if(collation == nil)
    {
        collation = [UILocalizedIndexedCollation currentCollation];
    }

    return collation;
}

- (NSArray *)collatedSections
{
    if(_collatedSections == nil)
    {
        int sectionTitlesCount = [[self.collation sectionTitles] count];

        NSMutableArray *newSectionsArray = [[NSMutableArray alloc] initWithCapacity:sectionTitlesCount];
        collatedSections = newSectionsArray;
        NSMutableArray *sectionsCArray[sectionTitlesCount];

        // Set up the sections array: elements are mutable arrays that will contain the time zones for that section.
        for(int index = 0; index < sectionTitlesCount; index++)
        {
            NSMutableArray *array = [[NSMutableArray alloc] init];
            [newSectionsArray addObject:array];
            sectionsCArray[index] = array;
            [array release];
        }


        for(NSManagedObject *call in self.fetchedResultsController.fetchedObjects)
        {
            int section = [collation sectionForObject:call collationStringSelector:NSSelectorFromString(name)];
            [sectionsCArray[section] addObject:call];
        }

        NSArray *sortDescriptors = self.fetchedResultsController.fetchRequest.sortDescriptors;
        for(int index = 0; index < sectionTitlesCount; index++)
        {
            [newSectionsArray replaceObjectAtIndex:index withObject:[sectionsCArray[index] sortedArrayUsingDescriptors:sortDescriptors]];
        }
    }
    return [[collatedSections retain] autorelease];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // The number of sections is the same as the number of titles in the collation.
    return [[self.collation sectionTitles] count];
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // The number of time zones in the section is the count of the array associated with the section in the sections array.
    return [[self.collatedSections objectAtIndex:section] count];
}


- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    if([[self.collatedSections objectAtIndex:section] count])
        return [[self.collation sectionTitles] objectAtIndex:section];
    return nil;
}


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


- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
    return [self.collation sectionForSectionIndexTitleAtIndex:index];
}

我希望仍然能够使用 FRCDelegate 协议来获得更新通知.似乎没有什么好办法让这两个对象很好地协同工作.

I would love to still be able to use the FRCDelegate protocol to be notified of updates. It seems like there is no good way making these two objects work together nicely.

推荐答案

由于无法对瞬态属性进行排序,所以我实现的解决方案是...

Since you cannot sort on a transient property, the solution I implemented is...

  1. 为 Core Data 模型中每个实体中的每个可排序属性创建一个名为sectionKey"的字符串属性.sectionKey 属性将是从基本属性(例如,名称或标题属性)派生的计算值.它必须被持久化,因为(当前)临时属性不能用于获取请求的排序描述符中.对将提供排序的每个 sectionKey 和基本属性启用索引.为了将此更新应用到现有应用程序,您需要执行轻量级迁移,并且还包括更新预先存在的数据库的例程.

  1. Create a string attribute called "sectionKey" for each sortable attribute within each entity in your Core Data model. The sectionKey attribute will be a calculated value derived from a base attribute (e.g., a name or title attribute). It must be persisted because (currently) a transient property cannot be used in a sort descriptor for a fetch request. Enable indexing on each sectionKey and base attribute for which sorting will be offered. In order to apply this update to an existing app, you will need to perform a lightweight migration, and also include a routine to update pre-existing databases.

如果您正在播种数据(例如,使用一组标准数据填充新安装,或者为每种目标语言创建本地化 SQLite 数据库,其中一个将在初始启动时复制),那么编码、计算和更新每个实体的 sectionKey 属性.关于播种数据的最佳"方法的意见各不相同,但值得注意的是,每种语言的少数 plist 文件(通常范围从几个字节到 20k,即使对于包含数百个值的列表也是如此)将离开与每种语言的单个 SQLite 数据库相比,总体占用空间要小得多(每种语言的起始量约为 20k).附带说明一下,可以将 Microsoft Excel for Mac 配置为通过启用语言功能 (3) 来提供本地化的列表排序.

If you are seeding data (e.g., to populate new installs with a standard set of data, or to create localized SQLite databases for each target language, of which one will be copied over on initial launch), in that code, calculate and update each entity's sectionKey attribute(s). Opinions vary as to the "best" approach to seeding data, however it's worth noting that a handful of plist files for each language (which will typically range from a few bytes to 20k, even for a list comprised of several hundred values) will leave a much smaller overall footprint than an individual SQLite database for each language (which start at about 20k each). On a side note, Microsoft Excel for Mac can be configured to provide localized sorting of lists by enabling the language features (3).

在获取结果控制器构造函数中,对 sectionKey 和 base 属性进行排序,并将 sectionKey 传递给部分名称键路径.

In the fetched results controller constructor, sort on the sectionKey and base attribute, and pass the sectionKey for the section name key path.

添加计算逻辑以更新所有添加或编辑用户输入中的 sectionKey 属性,例如,在 textFieldDidEndEditing: 中.

Add the calculation logic to update the sectionKey attribute(s) in all add or edit user inputs, for example, in textFieldDidEndEditing:.

就是这样!无需手动将获取的对象划分为数组数组.NSFetchedResultsController 将为您进行本地化排序.例如,在中文(简体)的情况下,获取的对象将通过拼音(4)进行索引.

That's it! No manual partitioning of fetched objects into an array of arrays. NSFetchedResultsController will do the localized collation for you. For example, in the case of Chinese (Simplified), the fetched objects will be indexed by phonetic pronunciation (4).

(1) 来自 Apple IOS 开发人员库 > 国际化编程主题 > 国际化和本地化.(2) TableViewSuite的3_SimpleIndexedTableView.(3) 如何在 Microsoft Office for Mac 中启用中文功能.(4) 汉语通常按笔画数或音标排序.

(1) From Apple IOS Developer Library > Internationalization Programming Topics > Internationalization and Localization.(2) 3_SimpleIndexedTableView of the TableViewSuite.(3) How to enable Chinese language features in Microsoft Office for Mac.(4) The Chinese language is commonly sorted by either stroke count or phonetic pronunciation.

这篇关于NSFetchedResultsController 与UILocalizedIndexedCollat​​ion的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 17:31