2011年7月2日土曜日

Cocoa ファイルの非同期コピー(5)

やはりファイルのコピーは鬼門かもしれない。これでファイルマネージャあきらめました、になってしまうポイントかも。

FileCopyManager(ファイルのコピー専門のクラス)を作ろうとしている。
ファイル1つのことなら非同期コピーで問題ない。FSCopyObjectAsyncを使えば簡単。

しかし複数のファイルなら・・・。ひとつひとつのファイルを非同期コピーしようとするとおかしなことになる。
単純化すると

for(NSURL* item in fileArray){
FSCopyObjectAsync(item to distURL)
}
とやるわけだが、これだと複数ファイル分非同期になるわけで、どのファイルのコピーが終わったとかどこまで進んだとか、管理しようがない。やはり複数ファイルの時は同期コピーにして、コピーの動作そのものを別スレッドに分ける必要があるようだ。

Finderでこのあたりの動作を確かめると、こんな風になっている。


単純なダイアログだと思っていたらけっこう複雑なTableViewだったのね。カスタムCellの描画が大変なことになっているような。
1行目はとあるFrameWorkのフォルダをコピー中。2行目はUbuntuのISOファイル。

おそらくFileCopyManagerみたいなクラスがあって、そいつはシングルトンで、コピー動作が来るたびにスレッドを分けながらダイアログを表示している、と。

なんだか難しいなー、と投げ出したくなる気分になったちょうどその時、

前向きないい変化を起こすには集中し、努力を続けることが必要 : ライフハッカー[日本版]

こんな記事が目に止まって「そうか、努力の持続が必要か」と思い直す。(^^;)

もう少しがんばってみよう。

2011年7月1日金曜日

暑い

Xcodeを起動しない日だったので日記風メモ。

・最高気温28℃。暑い。しかし夜には冷たい風が吹く。さすが北海道。エアコンの設定を28℃にしたとしたら、暖房が始まってしまいそうだ。

・通知表作業開始。毎度のことながら苦しむ。常日頃からちゃんと準備していないつけが。

・Win7を起動する。いつも「久しぶりに」起動する状態なので、起動するときはたいてい更新が始まる。裏でなにをやっているのかわからないんだけど、とにかく動作が異常に重たくなる。DropBoxの更新さえ「あと6時間」とか表示されると萎える。

・Windowsって「今日のパソコン」を体現するOSだよなー。Excelで仕事するから必要、という。じゃあOSXは?

2011年6月30日木曜日

Cocoa ファイルの非同期コピー(4)

というわけでFileCopyManagerを作成中。

こんなダイアログを表示しようと考えている。


コピーするファイルのサイズの合計、コピーしているファイルのサイズ、それぞれの進行状況、コピーしているファイル名及びアイコン、などなどを表示する。

cancelボタンも作ってみた。ということは、「複数コピーしているファイルのうちのひとつだけキャンセル」、「コピーそのもののキャンセル」といった処理も必要となる。

コピーをキャンセルということはコピー中のファイルも削除しないといけないわけで、なんとなくできるかどうか不安になるな。(^^;)

本日はinitメソッドを考えて、書いて、それでほぼ終了。
素人なので初期化ひとつとってもすらすらとはいかない。
今回のFileCopyManager、結局初期化はこんな風にした。

-(id)initWithDistURL:(NSURL*)dURL copyFileArray:(NSArray*)fArray{
    self=[super init];
    if(self){
        [NSBundle loadNibNamed:@"FileCopyDialog" owner:self];
        NSFileManager* fileManager=[NSFileManager defaultManager];
        BOOL isDir, valid;
        valid=[fileManager fileExistsAtPath:[dURL path] isDirectory:&isDir];
        if (!valid || !isDir) {
            return nil;
        }
        if([fArray count]<=0){
            return nil;
        }
        [self setDistURL:dURL];
        [self setFileArray:fArray];        
    }
    return self;
}

filemanagerを生成する必要はなかったけれど、最初はsourceURLも初期化の引数にしていたので生成している。結局、sourceURLはコピー元のフルパスがわかれば必要ないので割愛したが。

コピー先のURLが無効ならFileCopyManager自体を生成しないようにしているが、これって今考えたんだがあまりよろしくない。無効ならそのパスを作る、が正しい気がする。(ドラッグアンドドロップでのコピー操作をメインに考えているため、無効なパスへのコピー操作はそもそも発生しない、という事情もある)

distURLとfileArrayはpropatyでそれぞれ

@property (assign) NSURL*distURL;
@property (retain) NSArray* fileArray;

と宣言しているため、セッタゲッタが自動で作られるから、FileCopyManagerのオブジェクトを生成したあと、オブジェクトの外部からsetDistURLとする方法もあるわけで、この辺の使い分け方がまだよくわかっていない。

今回はコピー先やコピーファイル群が無効ならオブジェクトを生成しないでnilを返す、という方向でいいような気がしているが。

FileCopyManagerのオブジェクトがnilでないなら、[fileCopyManager startFileCopy]みたいなメソッドを呼び出せば呼び出し側の処理は終了、というふうにしようと考えている。

しかし残念ながら、明日からはいよいよ学期末モードに突入の予定。家で通知表作成の作業に入る。どうしてもExcelを使わないと済まないので、Winを起動せざるをえない。あまりプログラミングに時間がとれないなあ。悲しい。

2011年6月29日水曜日

Cocoa ファイルの非同期コピー(3)

FSCopyObjectAsyncの引数で指定したcallbackに、

FSFileOperationStage stage

というオペレーションの状態を表す変数が渡されてくるので、これがkFSOperationStageCompleteだったらダイアログを閉じるようにすればいい、と本日わかった。

現在のところ、処理すべきファイルのURLをNSArrayに入れて、そこからファイルを一つずつ取り出してコピーする、という段取りで処理している。これだと、1つのファイルを処理するたびにダイアログが現れては消える。

ま、それでも素人のプログラミングだからいいんだろうけど、ここはやはり「複数のファイルが指定されたら、相対のコピーサイズの進捗状況と単体のファイルの進捗状況」を両方表示できるようにしたい。

そんなわけでFileCopyManagerというクラスを作り始める。
ファイルのArrayを受け取って、コピーそのものとダイアログで進行状況を表示する、という働きをする予定。

しかしのっけから.nibファイルを動的に読み込む、というところでつまずいて本日は終了。(^^;)
どーなることやら。

しかし考えてみれば非同期コピーが曲がりなりにも実現できたので、かなりの前進だな。喜ぼう。

追記:
nibの動的な読み込みもやってみればどうということはなかった。NSViewControllerでinitWithNibName;するのを、nib読み込みだけ自前でやる、という感じ。

1,ダイアログのxib内のFile's Ownerを予め動的に読み込む予定のクラスにしておく
2,読み込み元クラスでIBOutletを作って、xib内でつないでおく
3、読み込み元クラスのinitあたりで、[NSBundle loadNibNamed:]でnibを読み込む

読み込んだ時点でIBOutletも有効になるようだ。案ずるより産むが易し。Cocoaはこういうことが多いかも。

2011年6月28日火曜日

Cocoa ファイルの非同期コピー(2)

ふむ、ちゃんとできるもんだ、非同期コピー。

昨日の参照サイトに書いてあったとおりにやってみたところ、見事に非同期コピーができた。
問題は、NSProgressIndicatorを置いたモードレスダイアログ。

表示して、NSProgressIndicatorをファイルのコピー状況に合わせて変化させるところまではいいとして、ファイルのコピーが終わってダイアログを閉じるところがわからない。(^^;)

callbackでコピーしたサイズがコピー元のファイルサイズを越えたところでダイアログを閉じるのかな。callbackはCの関数になるので、AppKitにアクセスするのが若干面倒なような。

もう少し研究。

2011年6月27日月曜日

Cocoa QLPreviewPanel失敗

QLPreViewPanelのコントローラーを今までと違うクラスにしようとして気軽に作業を始めて・・ハマってしまった。未だ解決できず。

順調に表示されていたPreviewが表示できなくなってストレスがたまる。さてどうしたものか。

このところやることが散漫で、十分あれこれ試すという姿勢が薄い。もともと薄いけど。もうすこし一つずつ着実に調べていくようにしよう。

追記:
QLPreviewPanelを表示する直前に

[[self window] makeFirstResponder:self];

とやると(ちなみにClassはNSViewのサブクラス)きちんと表示される。でもそんなんでいいのか?という疑問が・・・。結果オーライでいいのかなあ。

Cocoa ファイルの非同期コピー

そうか、スレッドとか使わないでも「ファイルの非同期コピー」をすればよかったのか。

「非同期コピー」という言葉も概念も知らなかったのが敗因。ま、知ることができてよかった。

日本語のの情報はこちらで。

Objective-Cで非同期ファイルコピー

サンプルプロジェクト付きの英語情報はこちらがいいかと。
Cocoa Tutorial: File Copy With Progress Indicator

特に後者のサンプルは作業進行度を表すインジケータの表示の仕方まで示した親切設計。

そろそろ在宅仕事が忙しくなるので、非同期コピーに果たして手をつけることができるのか・・。

2011年6月26日日曜日

Cocoa ファイルの種類

漫然とした1日。家族の用事やらなにやらであっという間に過ぎる。

プログラミングに対する集中力もなく、ちょっと調べては自分のプロジェクトを眺め、少し考えてはまたちょっと調べ、という感じでこれといって成果のない1日となった。ま、そんな日もあるさ。

IKImageBrowserViewでフォルダアイコンをダブルクリックしたらフォルダ内へ移動、はすぐできあがった。そりゃそうだ、NSTableViewでさんざんやったんだから。

delegateの

-(void)imageBrowser:(IKImageBrowserView*)aBrowser cellWasDoubleClickedAtIndex:(NSUInteger)index

を定義してダブルクリックの処理をしたので、フォルダでない場合は自分で書いてやらないと何も起こらない。とりあえず

[[NSWorkspace sharedWorkspace]openFile:[item fullPath]];

みたいな感じでファイルオープンだけするようにして、ここから少し考えた。ここの処理で、ファイルの種類によってあれこれやるのもおもしろいかな、と。単純にアプリケーションなら、「開く」か「実行」か、画像なら開くアプリの選択、とか。

IKImageBrowserViewで画像を自前で開けば、WindowsのVixみたいなアプリにもできるな、とか。

どこまで突き進むかわからないけれど、まずはクリックしたファイルの種類を判定するところから。

NSString* uti=[[NSWorkspace sharedWorkspace] typeOfFile:[item fullPath] error:nil];
UTIってなによ、な素人なわけだが、とにかくこれでファイルのUTIが取得できた。[item fullPath]はファイルのURLを収めたモデルクラス(のメソッド)。

NSString* loca=[[NSWorkspace sharedWorkspace] localizedDescriptionForType:uti];
これでいわゆる「ファイルの種類」を表す文字列が取得できた。ついでにEseのTableViewで表示できるようにしてみる。


えーと日本語で表示されないのは、アプリをローカライズしてないからかな?

それで以下のメソッドで「このタイプのファイル?」と問い合わせればBOOLで答えてもらえるみたい。

[[NSWorkspace sharedWorkspace] type:uti conformsToType:@"public.image"]);

上の例は画像かどうか問い合せてみた。NSLogを取ってみると、画像ならPNGでもJpegでもちゃんと「YES」を返してくれる模様。

そんなんでファイルの種類を得ることができたので、今度は

1,ファイルの種類を判定する専用のクラス
2,ファイルの種類に基づいてOpenする動作を割り当てるクラス

を細分化して書いてみようかなー、と考えてところで本日は終了。
QLPreviewPanelをちゃんと開くための作業をしようと思っていたけれど、なかなかうまく進まないものだ。

2011年6月25日土曜日

書店の風景

久しぶりに書店に行った。

木下誠氏のiOS関係の新刊書籍があれば買いたいなあ、と思っていたが、残念ながら並んでいなかった。

iOS開発におけるパターンによるオートマティズム
木下 誠
ビー・エヌ・エヌ新社
売り上げランキング: 56686

これですな。む・・今日発売?それなら並んでいるはずがないな、北海道なら。(2日遅れでありますな、なんでも)

で、書店のパソコン関連の棚を眺めてきたら・・・平台に並べているうち、3分の1がiPad関係。3分の1がスマートフォン関係。最後の3分の1が、なんとFaceBook関係の解説書。

売れるのかな、FaceBook関連。「ビジネスに活かす云々」みたいなタイトルが多かった気がする。
今だに「すぐできる〜」とかいう感じの入門書が多いものの、ネットがらみの書籍がずいぶん幅をきかせている感じがする。田舎だとプログラミング関係の本があまり手に入らなくて困る。この手の本ほど、実際に手にとってざっと中身を確かめてから買わないと危険なんだが。

Cocoa IKImageBrowserView(2)バインディングで表示する

なんのことない、すべて
こたつつきみかんさん

のこの2つのアーティクルのまんま作業したら見事に表示できた。

IKImageBrowserViewの使い方

IKImageBrowserViewの使い方 – 2

xcatsan師匠の文章と同じくらい、参考になるなあこのblogは。

以前、NSTreeControllerの実験用に作ったプロジェクトに、IKImageBrowserViewをはめこむ。で、上の2つのアーティクルどおりにバインディングでディレクトリ内のファイルを表示してみたらうまくいった。

で、以下の2点のみ自分で書き換えた。
いずれもIKImageBrowserViewItemプロトコル。
- (NSString *)imageRepresentationType
{
 return IKImageBrowserQuickLookPathRepresentationType;
}

- (id)imageRepresentation
{
 return [self fileURL];
}
こたつつきみかんさんでは

・IKImageBrowserNSImageRepresentationType

を指定してNSImageを渡すように書かれていたのを、IKImageBrowserQuickLookPathRepresentationTypeでNSURLを渡すように変更したところ、ほぼFinderライクな見た目となった。


速度も十分。以前、自分でカスタムCellを作ったときは/usr/bin内を表示させると激おそだったが、もちろんIKImageBrowserViewならそんなことはない。

いくつか不満もあって、たとえば表示用のIKImageBrowserCellのカスタマイズが簡単ではない(ように思える)こと、とか。ファイル名が長い場合、Finderなら2行に折り返しているけど、そういうカスタマイズはできないようだ、サブクラス化しても。

しかしとりあえずこれで「プレビューView」のめどはたった感じ。明日はdelegateメソッドを作ってフォルダアイコンをダブルクリックした場合は、という処理を付け加えよう。

2011年6月24日金曜日

OSXアップデート

10.6.8が来てるってことなのでアップデートしてみた。何が変わったのかは全然わかんないけど。

次はいよいよLion、だとか。

UIがけっこう変更されるということなので楽しみではある。

Cocoa IKImageBrowserView

QLPreviewPanelをTableViewのControllerで操作しているのはいくらなんでもまずいだろう(Tabごとにインスタンスが生成される)ということで、どのクラスで担当するか考える。

考えながら、そろそろTabを表示するところから全部書き直すかな、と思い始めた。

現在書いているプロジェクトはまだまだ実験用プロジェクトなわけだが、ある程度安定して動いているクラスを順次本番プロジェクトに書き写していく、というのもモチベーション維持のために必要かも。

飽きっぽいのでこのままいくと途中で放り出してしまう可能性もある。(^^;)

現在splitviewの右側のペインはTableViewで表示しているが、これをアイコン表示のViewと切り替えられるようにしたいし。

そのためのViewはひょっとしてIKImageBrowserViewがいいのかな、ということでこのクラスについて調べ始めた。以前TreeController調査用に作ったプロジェクトに組み込んで、うまく動くか試してみようと考えている。

そろそろ学期末の声が聞こえ始めて、そうそう遊びに時間をかけられなくなってくるなあ。早いところ仕事を終わらせてお楽しみに時間をかけられるようがんばろう。

2011年6月23日木曜日

追悼・元麻布春男氏

昨日急逝されたということで黙祷。

思えばずいぶん「スーパーアスキー」の記事を熱心に読んだ。

ショックだったのは、たしか氏は私と同世代のはず。出先で倒れてそのまま搬送先の病院で亡くなったようだ。明日は我が身。色即是空。諸行無常。

Cocoa QLPreviewPanel(2)

おそらく、日本語による10.6仕様QuickLook・QLPreviewPanelの解説、

Controllerと たわむれる11

とデベロッパドキュメントと、サンプルプロジェクト「QuickLookDownloader」のソースを読みながらQLPreviewPanelの勉強。

うーん、QLPreviewPanelControllerのプロトコルはNSViewControllerで定義してもだめなのか。たしかにデベロッパドキュメントでは「WindowControllerで実装するのがいいよ」みたいなことが書いてある。
QLPreviewPanelもまたシングルトンなので、Tabで複数表示されるTableViewにdatasourceやdelegateをあれこれ書いても仕方がない。

うーん、どうしよう、というところで本日は終了。

(追記)
masakihの日記
Controllerと たわむれる12

このアーティクルを読みながら、NSViewControllerをレスポンダチェーンに割り込ませてみたところ、見事QLPreviewPanelが意図通りに表示された。


やはりQLPreviewPanelControllerのプロトコルの問題だったか。

けっこうすっきりしたけど、ソースはすでにぐちゃぐちゃである。なんとかしたいなあ。

2011年6月22日水曜日

口唇ヘルペス

口唇ヘルペスという病気を発症した。といっても、ちょっとぴりぴりと痛みを感じる吹き出物が唇のそばにできただけだが、ネットでざっと調べたら抗生剤をのんだり塗り薬を塗ったりしないとけっこうひどいことになるらしい。

ということで病院へ。

ドクターからもらったパンフレットには「幼児期に感染した細菌が、体調が悪くなると引き起こす症状」とある。ふむふむ。ということは、これまでどんなに体調が悪くても発症しなかったけれど、50歳を間近にしてはげしく体力が落ちたためついに発症するようになった、と解釈するしかない。

ふー、いろいろあるもんだなあ。

本日は教室で教壇から脚を踏み外した拍子にけっこう激しくころんで膝を打って痛い思いもしたし、そういう日、ということなんだろうなあ。年を感じる日。

膝はけっこう具合が悪くて、といっても立ったり歩いたり、がんばれば走ったりもできるし日常生活に全く支障はないけれど、膝を曲げると鋭い痛みが走る。明日の朝がちょっと心配。

Cocoa QLPreviewPanel

気をとり直してQuickLook関連を調べ始める。

最初は選択したファイルをQLPreviewPanelで表示できればいい、と思っているわけだが、ドキュメントを読むとどうも「PreviewView」ともいうべき、「アイコンの代わりにPreviewがアイコン大に表示されるView」も作る方法がQuickLook関連でわかるかもしれない。わくわく。

とりあえずQLPreviewPanel。

先達のみなさまが親切なソースコード付きの解説をネットのあちこちに残してくれている。例えばいつものxcatsan師匠

Quick Look APIs(その2)

こんな感じで分かりやすく解説してくれている。しかし・・・OSX10.6以降、QuickLookの仕組みが大きく変わったらしく、解説されている方法は全然通用しない。

[[QLPreviewPanel sharedPreviewPanel] setURLs:list
currentIndex:0
preservingDisplayState:YES];

というメソッドがない、とすぐに弾かれてこれに気づいた。
デベロッパドキュメントの中を漁ると、まずはサンプルプロジェクトの「QuickLookDownloader」を調べるといいらしいことがわかる。

そうすると、
・Quick Look panel data source
・Quick Look panel delegate
のメソッドを定義した上、QLPreviewPanelに表示するデータクラスをQLPreviewItemプロトコル準拠にしないといけないようだ。

で、本日はここまで。

QLPreviewPanelを表示することはできたが、おそらくdelegateのpreviewPanel:sourceFrameOnScreenForPreviewItem:とpreviewPanel:transitionImageForPreviewItem:contentRect:を定義していないため、肝心のプレビューが表示されていないと思われる。

おもしろいのでさらに調べていこう。

2011年6月21日火曜日

Cocoa FrameWork

ファイルのコピーを別スレッド、あるいはGCDでやって見る方法を調べ始めて・・・こりゃ現在の知識と技術では全然理解出来ない、と判断した。

ちょいと調べて、というのは、究極の拡張版FinderというべきPath Finderの作者さんが公開しているライブラリ、というかFrameWork

Path Finder SDK / Open Source

をダウンロードして中身を覗いてみたり、

The Omni Group

がやはりオープンソースで提供している

omnigroup / OmniGroup

を覗いてみたりしたわけで、ファイルの操作をするだけでこれだけのclassが必要なのか、とがっくりする。Cocoaは比較的読みやすいソースコードになるのでここはじっくり勉強させてもらうことにして、当面は「高度なファイル操作」の実装はあきらめた。もっと勉強が必要だ。Windowsの「まめFile」みたいなインターフェイスでファイル操作をしたい、という要望は個人的に強いので、「すぐに作る」ことはあきらめるが作ることをあきらめたわけではない、と自分に言い聞かせてみる。あきらめたらそこで試合終了ですよ。

もともと.appディレクトリの中のリソースを手軽にプレビューするためにつくり始めたファイルマネージャだから、今後はそっち方面の研究をしていくことにしよう。

手軽にファイル操作をさせてもらえるFrameWorkってないのかな、とググったりして、世の中にはたくさんのCocoa用FrameWorkが存在することを知る。

ObjectLibrary

個人のページではここ

Uli's Web Site

が印象に残った。

2011年6月20日月曜日

Cocoa ファイルのコピー

大きなファイルのコピーを試す。
といっても手元にある大型ファイルといえばXcode3のインストールDVDイメージくらいだ。これは4Gあるのでとてもではないが繰り返しコピーして試す気にならない。膨大な時間がかかるに決まっている。

そこでubuntuの日本語RemixのCDイメージをダウンロード(^^;)。ごめんなさいこんなことに使って。およそ680Mなので、まあ耐えられる大きさだろうと予測する。

コピーしてみたところ、やはりファイルコピー用のSheetを表示したまま、長い時間待たされた。これはどう考えても、作業進捗状況をしめすインジケータ付きのダイアログを表示するのがマナーというものだな。

もちろんコピー中は他の作業ができなくなるわけなので、いよいよGrand Central Dispatch(GCD)について本腰を入れて調べる必要がある。本当に使いこなせるのか、激しく自信がないがやってみるしかないだろう。

ついでにFinderでファイルのコピーをしてみて、ダイアログの動作を観察。・・・どうやったら「ファイルをコピーしているスピード」とか「残り時間」を計算できるんだ?という疑問ばかりどんどんふくらむ。プログラミングをすればするほど、勉強することが山ほど増えていく不思議。

今日から「PTA広報づくり」という帰宅後の仕事が発生したので、さらに時間がないのが悩みだな。

2011年6月19日日曜日

Cocoa FSEvent と SCEvents(3)

アプリ起動時にひとつだけ生成されるTab管理のControllerでSCEventsのインスタンスを生成する。
Tabにはこんなふうに


表示しているディレクトリのフルパスを保存してあるので、それをNSMUtableArrayにしてSCEventsに渡し、

[events startWatchingPaths:tabTitles];

てな具合でファイルシステム監視の開始。これで無事動いている。
試しにFinder上でファイル操作をしてみたら、自作アプリでもちゃんとファイルの移動などを感知できていた。便利じゃのお。

ただ、Tabを削除してみたら見事にアプリが落ちた。(^^;)Tabを削除する前に

if([events isWatchingPaths]) [events stopWatchingPaths];

をしないといけなかった。
アプリが落ちたときに気づいたのだが、監視するパスの数だけスレッドが分かれるらしい。うーむ、なんだかすごいことになるな。

さて、次は・・・いよいよ大きなサイズのファイルのコピーかな。

2011年6月18日土曜日

アンダー・ザ・ドーム読了

アンダー・ザ・ドーム 下
スティーヴン・キング
文藝春秋
売り上げランキング: 8607

朝から晩までずっとこの本を読んで、10時半近くに読了。めずらしくプログラミングをひとつもしない日になったけれど、それでも満足。

物語のスケールだけからいうとかなり小さい。なんせ小さな町の中だけで終始する。当然敵役も「この程度でどうよ?」と疑問を感じながら読んだけど・・・ラストは納得。いい話だった。

時間的・空間的スケールという点で「スタンド」は偉大な作品だった。自分としては「スタンド」がキングのベスト1だ。

その後は・・・「シャイニング」かなあ。怖さという点では「ペットセマタリー」がかなり上位。
「アンダー・ザ・ドーム」は・・・どうだろう、「骨の袋」よりは下、「トミーノッカーズ」よりかなり上、というところ。

でも巻置く能わざる、という言葉にはぴったり。えぐい展開にページをめくるスピードが加速するというもんですよ。