UITableView的节头中的非US字符

时间:2010-01-30 12:26:00

标签: iphone uitableview core-data special-characters

我为简单的Core Data iPhone应用添加了部分列表。

我按照这个问题来创建它 - How to use the first character as a section name但我的列表中还包含以A-Z以外的字符开头的项目,特别是在瑞典使用的Å,Ä和Ö。

现在的问题是,当表格视图显示部分列表时,最后三个字符被绘制错误。见下图

现在看来我最好的选择就是让这些项目在“Z”下排序

if ([letter isEqual:@"Å"] ||
    [letter isEqual:@"Ä"] ||
    [letter isEqual:@"Ö"]) 
    letter = @"Z";

有人想过这个吗?

当我在它的时候......'Å','Ä'和'Ö'应按顺序排序,但按Core Data {''分类为'Ä','Å'和'Ö'{{ 1}}。我尝试将选择器设置为NSSortDescriptor,但这会产生localizedCaseInsensitiveCompare:错误。看到了吗?

7 个答案:

答案 0 :(得分:15)

所以我放不下这个,发现了以下内容:

在这种情况下,您需要做的是“Unicode规范化表格D”。在http://unicode.org/reports/tr15/(警告,冗长和干燥的文件)

中对此进行了更详细的解释

这是一个执行分解然后过滤掉所有变音符号的函数。您可以使用它将Äpple转换为Apple,然后使用第一个字母构建索引。

- (NSString*) decomposeAndFilterString: (NSString*) string
{
    NSMutableString *decomposedString = [[string decomposedStringWithCanonicalMapping] mutableCopy];
    NSCharacterSet *nonBaseSet = [NSCharacterSet nonBaseCharacterSet];
    NSRange range = NSMakeRange([decomposedString length], 0);

    while (range.location > 0) {
        range = [decomposedString rangeOfCharacterFromSet:nonBaseSet
            options:NSBackwardsSearch range:NSMakeRange(0, range.location)];
        if (range.length == 0) {
            break;
        }
        [decomposedString deleteCharactersInRange:range];
    }

    return [decomposedString autorelease];
}

(我在邮件列表上找到了这段代码,忘记了源代码,但我把它拿了一把并修了一下)

答案 1 :(得分:4)

我遇到原始问题中报告的相同问题,即扩展字符(Unicode页面0外)未正确显示在索引栏中。

虽然我似乎向NSFetchedResultsController提供了正确的单个unicode字符串,但我得到的是访问'sectionIndexTitles'属性的那些是高字节设置为0的相同字符;例如字符\ u30a2(KATAKANA LETTER A)变成\ \ u00a2(CENT SIGN)。

我不确定这是否是NSFetchedResultsController的方法 sectionIndexTitleForSectionName:中的错误或我自己在其他地方的错误,但是我的解决方法包括覆盖它并执行文档在内部执行的操作:

- (NSString *)sectionIndexTitleForSectionName:(NSString *)sectionName
{
    NSString    *outName;

    if ( [sectionName length] )
        outName = [[sectionName substringToIndex:1] uppercaseString];
    else
        outName = [super sectionIndexTitleForSectionName:sectionName];

    return outName;
}

这会产生预期的输出。

答案 2 :(得分:4)

只需在我的控制器中添加它就可以解决我原来的问题

- (NSString *)controller:(NSFetchedResultsController *)controller sectionIndexTitleForSectionName:(NSString *)sectionName {
return sectionName;}

Å,Ä和Ö在列表中正确显示

答案 3 :(得分:3)

当我遇到这样的情况时,我首先要问的是“苹果做了什么”。

作为一项实验,我刚刚将'Joe'pple'添加到我的iPhone地址簿中,并且他出现在普通的A下。我认为这很有意义。

所以不要把它们扔在Z或Ä下,你应该这样做。必须有某种方法来获取分组的unicode字符的“基本”字母。

答案 4 :(得分:2)

您可以使用UTF-8编码

const char *cLetter = (const char *)[ tmp cStringUsingEncoding:NSUTF8StringEncoding]; 
NSString *original = [NSString stringWithCString:cLetter encoding:NSUTF8StringEncoding];

答案 5 :(得分:1)

您是否按照我的answer来处理其他问题?

我正在做一些测试(重新获取我的对象)并看到奇怪的间歇性行为。它肯定会对它们进行正确排序(在'A'之后'Å',但在'Ä'之前'有时。其他时候,即使我没有做任何特别的事情,它也会把A-Z之外的人物放在最后(在'Z'之后)。

另外,我注意到如果你返回它的小写形式,'Å'被正确绘制。您是否尝试覆盖sectionIndexTitleForSectionName:以保留订单,但更改绘制的字符?

答案 6 :(得分:1)

你有没有解决过这个问题?

我已经能够通过实现sectionIndexTitlesForTableView来正确显示节标题索引:构建我自己的节标题数组:

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {

    NSMutableArray *indexKeys = [NSMutableArray arrayWithCapacity:30];
    NSArray *fetchedResults = [fetchedResultsController fetchedObjects];
    NSString *currKey = @"DEFAULT";

    for (NSManagedObject *managedObject in fetchedResults) {
        NSString *indexKey = [managedObject valueForKey:@"indexKey"];
        if (![indexKey isEqualToString:currKey]) {
            [indexKeys addObject:indexKey];
            currKey = indexKey;
        }
    }

    return indexKeys;
}

这里,indexKey是名字的第一个字母。

但是,这会在sectionForSectionIndexTitle中创建两个问题之一:而不是:

如果我只是返回该部分的索引,那么它现在是未排序的索引,不再与fetchResultController中的排序顺序相对应:

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

或者,如果我将调用传递给fetchedResultsController,它会破坏非美国索引标题,因为它们不再是fetchedResultsController使用的奇怪字符:

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

导航到“Ø”索引标题后,后一代码会产生以下类型的错误:

  

由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'24处的索引标题不等于'Ø''

解决这个问题的方法是将有问题的角色转换回他们怪异的自我:

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
    if ([title isEqualToString:@"Æ"]) {
        title = @"\u2206";
    } else if ([title isEqualToString:@"Ø"]) {
        title = @"\u0178";
    } else if ([title isEqualToString:@"Å"]) {
        title = @"\u2248";
    }
    return [fetchedResultsController sectionForSectionIndexTitle:title atIndex:index];
}

您可以使用“将描述打印到控制台”操作在调试器中找到Unicode值。

然而,好的解决方案是弄清楚为什么会出现这种奇怪的编码并阻止它。