差分
このページの2つのバージョン間の差分を表示します。
blog:2013:2013-02-16 [2013-02-16 23:16] Decomo 作成 |
blog:2013:2013-02-16 [2015-01-06 11:51] |
||
---|---|---|---|
行 1: | 行 1: | ||
- | ====== NSArrayをFinder風の並び順でソートする ====== | ||
- | こんなファイルがあったとする。 | ||
- | |||
- | file-a | ||
- | file-1 | ||
- | file-01 | ||
- | file-2 | ||
- | file-10 | ||
- | file-b | ||
- | file-ab | ||
- | |||
- | 辞書式で並べ替えると | ||
- | |||
- | file-01 | ||
- | file-1 | ||
- | file-10 | ||
- | file-2 | ||
- | file-a | ||
- | file-ab | ||
- | file-b | ||
- | |||
- | となるわけだが、Finderでソートすると | ||
- | |||
- | file-1 | ||
- | file-01 | ||
- | file-2 | ||
- | file-10 | ||
- | file-a | ||
- | file-ab | ||
- | file-b | ||
- | |||
- | となる。連続した数字部分を数値と見なし、数値順で並べてくれる。個人的にはこの方が分かりやすくて好きだ。 | ||
- | |||
- | で、この数値順ソートをCocoaで実現するにはどーしたらいいのかなー?と思って調べていたら、[[http:// | ||
- | |||
- | 上記Q& | ||
- | |||
- | < | ||
- | |||
- | <code objc> | ||
- | #include < | ||
- | #include < | ||
- | |||
- | static CFComparisonResult CompareLikeTheFinder(const void *val1, const void *val2, void *context) | ||
- | { | ||
- | SInt32 | ||
- | CFStringRef | ||
- | CFStringRef | ||
- | CFIndex | ||
- | CFIndex | ||
- | UniChar | ||
- | UniChar | ||
- | |||
- | // val1 is the left-hand side CFString. | ||
- | // val2 is the right-hand side CFString. | ||
- | if (context) | ||
- | { | ||
- | NSString *key = (NSString *)context; | ||
- | lhsStr = (CFStringRef)[(NSObject *)val1 valueForKey: | ||
- | rhsStr = (CFStringRef)[(NSObject *)val2 valueForKey: | ||
- | } | ||
- | else | ||
- | { | ||
- | lhsStr = (CFStringRef)val1; | ||
- | rhsStr = (CFStringRef)val2; | ||
- | } | ||
- | lhsLen = CFStringGetLength(lhsStr); | ||
- | rhsLen = CFStringGetLength(rhsStr); | ||
- | |||
- | // Get the actual Unicode characters (UTF-16) for each string. | ||
- | CFStringGetCharacters(lhsStr, | ||
- | CFStringGetCharacters(rhsStr, | ||
- | |||
- | // Do the comparison. | ||
- | UCCompareTextDefault( | ||
- | | ||
- | | kUCCollateWidthInsensitiveMask | ||
- | | kUCCollateCaseInsensitiveMask | ||
- | | kUCCollateDigitsOverrideMask | ||
- | | kUCCollateDigitsAsNumberMask | ||
- | | kUCCollatePunctuationSignificantMask, | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | NULL, | ||
- | & | ||
- | ); | ||
- | |||
- | // Return the result. Conveniently, | ||
- | // returns -1, 0, or +1, which matches the values for | ||
- | // CFComparisonResult exactly. | ||
- | return (CFComparisonResult)compareResult; | ||
- | } | ||
- | |||
- | static void SortCFMutableArrayLikeTheFinder(CFMutableArrayRef array, CFStringRef key) | ||
- | { | ||
- | CFArraySortValues( | ||
- | array, | ||
- | CFRangeMake(0, | ||
- | CompareLikeTheFinder, | ||
- | key | ||
- | ); | ||
- | } | ||
- | |||
- | @interface NSMutableArray (PKAdditions) | ||
- | - (void)sortByFinderOrder; | ||
- | - (void)sortByFinderOrderWithStringObjectKey: | ||
- | @end | ||
- | |||
- | @implementation NSMutableArray (PKAdditions) | ||
- | - (void)sortByFinderOrder | ||
- | { | ||
- | [self sortByFinderOrderWithStringObjectKey: | ||
- | } | ||
- | |||
- | - (void)sortByFinderOrderWithStringObjectKey: | ||
- | { | ||
- | SortCFMutableArrayLikeTheFinder(self, | ||
- | } | ||
- | @end | ||
- | </ | ||
- | |||
- | 実際のファイル名やディレクトリ名をソートする場合は、< |