ソースの表示以前のリビジョンバックリンク全て展開する/折り畳む文書の先頭へ Share via Share via... Twitter LinkedIn Facebook Pinterest Telegram WhatsApp Yammer Reddit Teams最近の変更Send via e-Mail印刷パーマリンク × « Portsにnetatalk 3.0.2がキタ━━━(゚∀゚)━━━ !!!!! Disk Arbitration Frameworkでディスクのマウントを抑制する » 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で実現するにはどーしたらいいのかなー?と思って調べていたら、Technical Q&A QA1159: Sorting Like the Finderという、そのまんまの記事がADCにあった。流石林檎様、分かっていらっしゃる。 上記Q&Aのコードを改造してNSMutableArrayのカテゴリメソッドにするとスマートに使えて良い感じ。 NSString配列のソートはもちろん、任意のオブジェクトの場合はソートに使うNSStringインスタンス変数名をsortByFinderOrderWithStringObjectKey:に渡せばおk。 #include <CoreServices/CoreServices.h> #include <sys/param.h> static CFComparisonResult CompareLikeTheFinder(const void *val1, const void *val2, void *context) { SInt32 compareResult; CFStringRef lhsStr; CFStringRef rhsStr; CFIndex lhsLen; CFIndex rhsLen; UniChar lhsBuf[MAXPATHLEN]; UniChar rhsBuf[MAXPATHLEN]; // 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:key]; rhsStr = (CFStringRef)[(NSObject *)val2 valueForKey:key]; } 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, CFRangeMake(0, lhsLen), lhsBuf); CFStringGetCharacters(rhsStr, CFRangeMake(0, rhsLen), rhsBuf); // Do the comparison. UCCompareTextDefault( kUCCollateComposeInsensitiveMask | kUCCollateWidthInsensitiveMask | kUCCollateCaseInsensitiveMask | kUCCollateDigitsOverrideMask | kUCCollateDigitsAsNumberMask | kUCCollatePunctuationSignificantMask, lhsBuf, lhsLen, rhsBuf, rhsLen, NULL, &compareResult ); // Return the result. Conveniently, UCCompareTextDefault // 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, CFArrayGetCount(array)), CompareLikeTheFinder, key ); } @interface NSMutableArray (PKAdditions) - (void)sortByFinderOrder; - (void)sortByFinderOrderWithStringObjectKey:(NSString *)key; @end @implementation NSMutableArray (PKAdditions) - (void)sortByFinderOrder { [self sortByFinderOrderWithStringObjectKey:nil]; } - (void)sortByFinderOrderWithStringObjectKey:(NSString *)key { SortCFMutableArrayLikeTheFinder(self, key); } @end 実際のファイル名やディレクトリ名をソートする場合は、- [NSFileManager displayNameAtPath:(NSString *)path]で得られる名前をソートしないとFinder順にはならない。なぜかというと、Finderから見えるディレクトリ名はローカライズ(~/Documents → 書類 みたいなの)された物なので。 Comments Name E-Mail Website 人間の証明として、ボックス内の全ての文字を入力してください。 この項目は空のままにして下さい:Preview Comment blog/2013/2013-02-16.txt 最終更新: 2015-01-06 11:51(外部編集)