4

私はContactBookアプリを作成しており、AddressBookから名前を取得してコアデータに保存しNSFetchedResultsController.However、最初のインデックスを使用してテーブルに名前を表示し、最初に表示されるセクションにアルファベットが続きます。しかし、ネイティブの連絡先アプリのようにやりたいのです。つまり、#インデックスがついに来るはずです。
私は以下を使用しましたNSortDescriptor

sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@ "fullName" ascending:YES];

ここで「fullName」は、key名と名前を連結して作成されたコアデータです。fullNameまた、セクション識別子は、がアルファベットで始まらない場合は「fullName」の最初の文字であり、そのセクション識別子は#です。
私はそれについて検索NSDiacriticInsensitiveSearchしてコンパレータで使用しましたNSortDescriptorが、機能しませんでした。誰かが何か考えを持っているなら、私に知らせてください。

これが私のコードです:

NSString *special = @"\uE000";
if ([[self sectionName:contactName] isEqualToString:@"#"]) {                           
    sortName = [special stringByAppendingString:contactName];
}
else{
    sortName = contactName;
}
[newContact setValue:[self sectionIdentifier:sortName] forKey:@"sectionIdentifier"];
[newContact setValue:sortName forKey:@"sortName"];

そして、ここにソート記述子があります:

sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"sortName" ascending:YES];

[self sectionIdentifier:sortName]このメソッドは、sortNameがアルファベット以外で始まる場合は#を返し、そうでない場合は開始元のアルファベットを返します。

newContactはエンティティのオブジェクトです。

4

4 に答える 4

6

名前が文字で始まる場合、またはそうでない場合sortNameは、追加の属性をエンティティに格納できます。すべての文字よりも「大きい」固定文字です。例えばfullName<C>fullName<C>

NSString *special = @"\uE000";
if ("fullName starts with letter")
    sortName = fullName;
else
    sortName = [special stringByAppendingString:fullName];

に従ってソートできるようになりました。特殊文字で始まるsortName場合、セクション識別子は「#」になります。sortName

欠点は、追加の属性を保存する必要があることです。利点は、フェッチされた結果コントローラーを引き続き使用できることです (これは、並べ替えに永続的な属性のみを使用できます)。

更新:実際にはもう少し簡単に行うことができます。

新しいエントリを作成するとき、sectionIdentifier文字の場合は名前の最初の文字に設定し、それ以外の場合は特殊文字に設定します。

NSString *special = @"\uE000";

if ([[NSCharacterSet letterCharacterSet] characterIsMember:[contact.contactName characterAtIndex:0]]) {
    contact.sectionIdentifier = [contact.contactName substringToIndex:1];
} else {
    contact.sectionIdentifier = special;
}

フェッチされた結果コントローラーはsectionIdentifier、セクションのグループ化と並べ替えに使用します。各セクション内のエントリは次の順に並べ替えられcontactNameます。

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Contact"];
NSSortDescriptor *sort1 = [NSSortDescriptor sortDescriptorWithKey:@"sectionIdentifier"
             ascending:YES selector:@selector(localizedStandardCompare:)];
NSSortDescriptor *sort2 = [NSSortDescriptor sortDescriptorWithKey:@"contactName"
             ascending:YES selector:@selector(localizedStandardCompare:)];
[request setSortDescriptors:@[sort1, sort2]];
self.frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                   managedObjectContext:self.context
                     sectionNameKeyPath:@"sectionIdentifier"
                              cacheName:nil];

文字以外のエントリはすべて、最後のセクションにグループ化されます。#最後のステップは、最後のセクションの正しいセクション ヘッダーを表示することです。

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.frc sections] objectAtIndex:section];
    NSString *title = [sectionInfo name];
    if ([title isEqualToString:special])
        title = @"#";
    return title;
}
于 2012-10-17T18:24:05.297 に答える
2

結果を 2 つの配列 (英字で始まる配列とそうでない配列) に分割できます。次に、2つを一緒に追加します。と呼ばれる管理対象オブジェクトの配列から始めていると仮定しますresults

//Create the sort descriptor array
NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:@"fullName" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject:sd];

//Create a sorted array of objects where fullName starts with an alpha character
//using a Regex

NSPredicate *pred = [NSPredicate predicateWithFormat:@"fullName MATCHES '^[a-zA-Z].*'"];

NSArray *alpha = [[results filteredArrayUsingPredicate:pred] sortedArrayUsingDescriptors:descriptors];

//Now use the alpha array to create an array of objects where the fullName does not
//start with an alpha character

NSMutableArray *nonAlpha = [results mutableCopy];

[nonAlpha removeObjectsInArray:alpha];

[nonAlpha sortUsingDescriptors:descriptors];

//Now put them back together again

NSArray *sortedResults = [alpha arrayByAddingObjectsFromArray:nonAlpha];

//And if you're not using ARC!
[nonAlpha release];
于 2012-10-12T19:58:56.020 に答える
1

あなたはこれを行うことができます:

sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"fullName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];

あなたの場合のパフォーマンスに影響を与えないことを確認してください。

于 2012-10-09T12:56:02.513 に答える
0

独自のコンパレータ関数を書いてみてください

それがManagedObjectsをソートしていて、それらすべてがフィールドとしてfullNameを持っていると仮定すると、以下が役立つかもしれません。

[[NSSortDescriptor alloc] initWithKey:@"FullName" ascending:YES comparator:^NSComparisonResult(id obj1, id obj2) {
        return [[obj1 objectForKey:@"fullName"] compare:[obj2 objectForKey:@"fullName"] options:NSCaseInsensitiveSearch];
    }];

これの利点は、比較ごとにNSLogを記述して、何が起こっているかを確認できることです。

于 2012-10-12T04:39:57.700 に答える