2011年7月4日月曜日

Cocoa ファイルの非同期コピー(7)Copyの進捗状況を表示する

たくさんあちこちにbugを含みつつ、とりあえずこんな感じのダイアログを表示しようとしている。


インジケータにコピーしたbytesを表示していくわけだが、これがどうもうまくいかないので調べてみる。

FSCopyObjectAsyncのcallbackには自クラスのselfを引数で渡して、自クラスのメソッドをさらにcallbackする。このほうがIBOutletとかをいじるのが簡単だし、なにかとCocoaスタイルのほうが初心者には都合がいい。で、そのcallbackのcallbackメソッドの中で

bytesCompleted = (CFNumberRef) CFDictionaryGetValue(statusDictionary, kFSOperationBytesCompleteKey);
という風にコピー済みbyteを得ているが、複数ファイルをいっぺんに非同期コピーしていると「どのファイルが、どれだけコピー済みか」がわからない。
そこでcallbackの中でコピー中のファイルのURLを得るようにして、それをcallbackのcallback(・・ええい、面倒くさい)に渡すようにしてみた。

だからcallbackのcallbackはこうなっている。
          FileOperationStage: (FSFileOperationStage) stage
                      Status:(OSStatus) error
               DictionaryRef:(CFDictionaryRef)statusDictionary
                  currentURL:(NSURL*)aURL{
最後のaURLが現在コピー中のファイルのURL。で、callbackが呼ばれるたびにこのURLの中身をNSLogしてみると、なんと、「コピー元」と「コピー先」の両方のファイルについて、それぞれcallbackが呼ばれていることがわかった。

つまり、

/hoge/hoge.txt

から

/hage/hoge.txt

にコピーするとして、コピー元/hoge/hoge.txtが100Kbytes分転送されたらcallbackが呼ばれ、コピー先/hage/hoge.txtが100K転写されたらもう1回callbackが呼ばれ、単純に「コピー済みbytes」を合計すると2倍の数値を得ることになってしまう。だからインジケータがすぐに動かなくなるのか。

そこで

[copyComplatedbytesOfFiles setObject:compBytes forKey:[[aURL path] lastPathComponent]];

みたいなNSMutableDictionaryを作っておいて、hoge.txtが何byte転送済みかを記録しておくことにしてみた。

で、
for(NSNumber* num in bytesArray){
allFileComplatedByte+=[num doubleValue];
}

辞書内のコピー済みbytesを集計してインジケータに設定する、と。

たったこれだけのことだけど、思った通りの動作をしてうれしい。問題はコードがめちゃくちゃ汚いことだな。(^^;)書きなおそう。

あとはこの動作全体をNSOperationに入れてやればいいのだろうが、非同期コピーなので大きなファイルをコピー中に他のファイルをコピーしても十分動作する。これでいいかなあ。
問題はダイアログがぴったり重なって表示されることだなあ。

0 件のコメント:

コメントを投稿