アーカイブ

Posts Tagged ‘AppKit’

Mangaoにrarファイル対応をコミットしました

OS X用のコミックビューア、Mangaoにrarファイル対応をコミットしました。
http://ryotaminami93.appspot.com/mangao.html

中の人からtwitter経由で「Mangaoにgithubで公開しているzipファイルのライブラリを使ったよ」という連絡があったので使ってみたのですが、

  • シンプルなのでストレスが少ない
  • キーボードの操作方法がDOSのコンソールアプリみたいで好み
  • OS X 10.8で安定している(Simple ComicやcooViewerの問題点)

事が解りました。

ソースコードも公開されていますし、ちょっと手伝いたい気持ちになったのでrarファイルの対応を行って、中の人にコードレビューして頂きました。
幸い気に入って頂けたようなので、無事マージされたバージョンがリリースされています。
rar対応の部分のライブラリは切り出して、別途githubでも公開しています。
https://github.com/marvelph/RarFile

広告
カテゴリー:開発 タグ: ,

アプリケーションパッケージ名とアプリケーションメニューのローカライズ方法は異なる

OS Xのアプリケーションパッケージの名前をローカライズした所、Finder上では正常にローカライズされているのに、起動後のアプリケーションメニューのタイトルがローカライズされないという現象に遭遇しました。
そこでよくよくドキュメントを調べてみたら、パッケージ名とメニュータイトル及びアバウトダイアログでは、参照している情報が異なる事に気がつきました。
正常にローカライズできなかったのは、アプリケーションパッケージに必要なCFBundleDisplayNameだけが設定してあり、メニュータイトルに必要なCFBundleNameが抜け落ちていた事が原因です。

アプリケーションパッケージの場合

  • Info.plistにCFBundleDisplayNameを追加する。値は英語版の名前で良い。
  • 言語別のInfoPlist.stringsでCFBundleDisplayNameをローカライズする。
  • Info.plistにLSHasLocalizedDisplayNameを追加する。値は真。

LSHasLocalizedDisplayNameはiPhoneでは見かけないキーですが、ドキュメントによるとCFBundleDisplayNameの検索速度が向上する事になっています。

メニュー及びアバウトダイアログの場合

  • Info.plistにCFBundleNameを追加する。値は英語版の名前で良い。
  • 言語別のInfoPlist.stringsでCFBundleNameをローカライズする。

今回のトラブルは、こちらが抜けている事が原因でした。

カテゴリー:開発 タグ: ,

NSMenuItemのenabled以外の属性の更新

Cocoaでメニューの有効・無効を制御する場合、レスポンダ側にNSMenuValidationを実装します。
対象になるメニューに対して、レスポンダチェーンのどこかでvalidateMenuItem:がYESを返した場合は有効、それ以外の場合は無効に設定されます。

類似の処理として、メニューアイテムにチェックマークを付けたり、タイトルを修正したい事があります。
validateMenuItem:にはメニューアイテムも渡ってくるので、有効を返す前にメニューアイテムにチェックマークを設定してやれば良いかと思いましたが、問題がある事が判りました。
有効・無効の場合とは異なり、メニューアイテムその物を変更してしまっているので、別のタイミングで明示的にチェックマークを外さない限り、マークが付いたままになります。
レスポンダチェーンがどこも反応しない場合に、チェックマークが無い状態に戻ると勘違いしていたのです。

ここを正しく実装するためには、チェックマークを付けたりタイトルを修正する可能性のあるメニューアイテムはすべて、アプリケーションデリゲートのvalidateMenuItem:で初期状態に戻す必要があるという事です。
アプリケーションデリゲートがレスポンダチェーンから外れる事は無いので、必ずメニューを更新する事ができます。

カテゴリー:開発 タグ: ,

NSTableViewを参照オブジェクトのフィールドでソートする

NSTableViewをカラムヘッダクリックによってソートする場合、デリゲートでtableView:sortDescriptorsDidChange:を受けて、データソースをソートします。
この時NSSortDescriptorの配列が渡ってくるのですが、ここにはソートに使うカラム名と順序が入っています。
オブジェクトが一つでないのは、いくつかのカラムをクリックした場合にそのソート履歴を残しておいて、比較結果が同一の場合の第二比較条件に使うためです。
例えば名前カラムの次に年齢カラムをクリックした場合、まず年齢でソートが行われますが、同一年齢の要素はさらに名前でソートされます。

NSTableViewがNSSortDescriptorを生成する時に使うカラム名は、NSTableColumnにsetSortDescriptorPrototype:で設定しておきます。
通常データソースはNSMutableArrayに詰め込まれたオブジェクトの配列で、NSSortDescriptorが指定するカラム名をキーバリューコーディングで解決してソートを行います。

ここで、次のようなケースを考えます。
テーブルに住所録が表示されていて、そのカラムに会社名が存在するケースです。
モデルは、以下のようになります。

@interface Organization : NSObject {
    NSString *name;
    NSString *address;
}

@interface Person : NSObject {
    NSString *name;
    NSInteger *age;
    NSString *address;
    Organization *organization;
}

Personのorganizationはnilの場合もあり、その場合は無所属です。
ここでNSTableViewに住所録を表示したとして、カラムに組織名があった場合、そのNSSortDescriptorのキーは次のように指定する事ができます。

[[NSSortDescriptor alloc] initWithKey:@"organization.name" ascending:YES selector:@selector(compar:)];

organizationのnameがnilの場合や、organizationがnilの場合でも正常に動作します。

キーバリューコーディングにおけるピリオドを使った参照オブジェクトの指定は、tableView:objectValueForTableColumn:row:を実装する時にも使えると思います。

カテゴリー:開発 タグ: ,

nibファイルのテキスト形式

nibファイルをテキスト形式で扱う場合に、微妙な罠がみつかりました。
ボタンのショートカットにreturnキーを当ててデフォルトボタンにすると、キャリッジリターンコードがXMLのテキスト部分に素で現れます。
ツールやエディタによっては問題がおきるので、エンコードして欲しい所です。

カテゴリー:開発 タグ: