誰も解決策を提供できないように見えるので、思いついた解決策を投稿しようと思いました。まず、データのモデルを作成しました。
@interface MyModel : NSObject
{
NSString* _value;
NSString* _sortableValue;
}
@property (nonatomic,copy) NSString* value;
- (NSString*)sortableValue;
- (NSString*)comparableString:(NSString*)str;
@end
モデルの鍵となるのは、sortableValue の作成に使用される comparisonString メソッドです。モデルの実装は次のとおりです。
@implementation MyModel
@synthesize value=_value;
-(void)dealloc
{
[_value release];
[_sortableValue release];
[super dealloc];
}
- (void)setValue:(NSString*)value
{
[_value release];
_value = [value copy];
[_sortableValue release];
_sortableTValue = nil;
}
- (NSString*)sortableValue
{
if (_sortableValue == nil)
_sortableValue = [[self comparableString:_value] retain];
return _sortableValue;
}
- (NSString*)comparableString:(NSString*)str
{
if (str == nil)
return nil;
else if ([str length] == 0)
return [NSString stringWithString:str];
NSCharacterSet* numbersSet = [NSCharacterSet decimalDigitCharacterSet];
if ([str rangeOfCharacterFromSet:numbersSet options:0 range:NSMakeRange(0, 1)].location != NSNotFound)
return [NSString stringWithString:str];
NSRange range = NSMakeRange(0, [str length]);
if ([str compare:@"a " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 2)] == NSOrderedSame)
range.location = 2;
else if ([str compare:@"an " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 3)] == NSOrderedSame)
range.location = 3;
else if ([str compare:@"the " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 4)] == NSOrderedSame)
range.location = 4;
range.length -= range.location;
NSCharacterSet* lettersSet = [NSCharacterSet letterCharacterSet];
NSUInteger letterOffset = [str rangeOfCharacterFromSet:lettersSet options:0 range:range].location;
if (letterOffset == NSNotFound)
return [NSString stringWithString:str];
letterOffset -= range.location;
range.location += letterOffset;
range.length -= letterOffset;
return [str substringWithRange:range];
}
@end
文字列から先頭の記事を削除するだけでなく、先頭の文字以外の文字も削除します。iPod ライブラリに「$ell Your $oul」というタイトルの曲があり、MPMediaPickerController の E セクションに配置されます。最初の並べ替えアルゴリズムを作成した場合に、それができたかどうかはわかりませんが、MPMediaPickerController との一貫性を保つつもりでした。
パズルの最後のピースは UILocalizedIndexedCollation クラスです。この便利な小さなヘルパー クラスを使用すると、データを並べ替えて、UITableViewDataSource を介して UITableView にデータを簡単に提供できます。モデルと組み合わせて UILocalizedIndexedCollation クラスを使用する方法のスニペットを次に示します。
// tableData will contain an NSArray for each populated section in the table view
NSMutableDictionary* tableData = [NSMutableDictionary dictionary];
NSMutableArray* myArray = [NSMutableArray array];
// Populate myArray with instances of MyModel
UILocalizedIndexedCollation* indexer = [UILocalizedIndexedCollation currentCollation];
for (MyModel* data in myArray)
{
NSInteger index = [indexer sectionForObject:data collationStringSelector:@selector(sortableValue)];
NSNumber* key = [[NSNumber alloc] initWithInteger:index];
NSMutableArray* array = [tableData objectForKey:key];
if (array == nil)
{
array = [NSMutableArray new]; // Will be released after creating a sorted array in the following section
[tableData setObject:array forKey:key];
}
[array addObject:data];
[key release];
}
[tableData enumerateKeysAndObjectsUsingBlock:^(id key, id array, BOOL* stop)
{
NSMutableArray* sortedArray = [[indexer sortedArrayFromArray:array collationStringSelector:@selector(sortableValue)] mutableCopy];
[tableData setObject:sortedArray forKey:key];
[array release];
}];
UILocalizedIndexedCollation に関する簡単なメモ (Apple のドキュメントから):
アプリケーションが現在の言語設定の Localizable.strings ファイルを提供する場合、インデックス付き照合オブジェクトは、selector によって識別されるメソッドによって返される各文字列をローカライズします。
そのため、サポートする言語ごとに Localizable.strings を提供するようにしてください。そうしないと、テーブル ビューにセクション AZ と # しかありません。
これに関するすべての詳細を理解するのにしばらく時間がかかったので、他の人に役立つことを願っています. これを改善する方法があれば教えてください。