sci

最果て風呂

mto を Cocoa で実装してみる

Cocoa で実装することができた

関連付け

IBAction は HTML の Form でいうところの name プロパティに相当するのかな?ということに気付いて、

- (IBAction)ClearInput:(id)sender;

をボタンの数だけ作成(名前は小文字からはじめた方がよいのだろうけど)した。そしてこれを xib の画面で接続していく。この「接続」って行為がわからなかったんだよね。

テキストエリアの文字列をクリア

まずはテキストエリアにある文字列を消去ボタンを押してクリアできるようにしてみようかな。う〜ん、たったこれだけのことなのに出来ない。何でなん?

やっとテキストエリアの文字をクリアすることが出来た。

@property IBOutlet NSScrollView *inputTextArea;
@property IBOutlet NSScrollView *resultTextArea;

@property IBOutlet NSTextView *inputTextArea;
@property IBOutlet NSTextView *resultTextArea;

にしないとダメなのだった。こうしないと .string で操作できないのだ。テキストエリアの接続は古いまま(NSScrollView)になっているので、一旦削除して接続し直した。

実装は下記のように @"" で空にした。

- (IBAction)ClearInput:(id)sender {
    _inputTextArea.string = @"";
}

テキストエリアの文字列を移動

次にやることは、変換後テキストエリアの文字列を変換前テキストエリアに移動することだね。できたできた。結果エリアの文字列を入力エリアに移動することが出来たけど、移動後に変換後テキストエリアに文字列が残ってしまうは嫌なので、先と同じように空にした。

- (IBAction)ResultToInput:(id)sender {
    _inputTextArea.string = _resultTextArea.string;
    _resultTextArea.string = @"";
}

外部ファイルの辞書を内部に取り込む

次は辞書の読み込みだね。CUI 版のやつをコピペして ARGV 関係の処理を削除していろいろ。Xcode のビックリマークが消えない。辞書をどうやって指定しましょ〜。

NSString *kanadict = @"/Users/hoge/project/mto/dict/kana-jisyo";
NSString *kanjidict = @"/Users/hoge/project/mto/dict/kanji-jisyo";

import 文の後に書いてやれば認識できるようだ。これはグローバル変数になるのかな?

あ〜忘れてたわ。createDict_innerDict という内部辞書を持った mto インスタンスを作成して printDict メソッドを使って表示するという流れだった。オブジェクト指向難しい。

どうにか Xcode 内のコンソールに内部辞書の要素数を表示することが出来るようになった。CUI 版から持ってきた処理は何も変更せずにそのまま使えた。ここまでくれば先は見えたね。

変換処理毎に辞書を新しく作成させる方針はそのままにしておくけど、この _innerDict ってどんな寿命なのだろう?わかってない……。取り敢えず処理毎に空にさせるようにしたけれど、clearDict をしなくても問題はないような動きをしている。同じ名前の _innerDict だけれど、インスタンス ID は異なるから中身は新しくなっている別物のかな?

う〜、コンソールに文字列の置換結果を表示できるようになったけど、テキストエリアに表示(反映)させることが出来ない。あとちょいなんだけどなぁ。

経験が役に立った

できたできた、HTML 版と同じような感じで実装してやっと動いたわ。辞書は決め打ちになっいるけれど、インプットエリアの旧仮名を新仮名に変換してアウトプットエリアに表示させることができた!

6 種類ある変換を実装することができた。あとは辞書ファイルをどうするかだね。アプリケーションに内包するか、好きな場所に置いて設定でそれを読み込ませるようにするかだ。Mac 的には内包してしまうのがよいのだろうね。

調べてみると、このプロジェクトの作成日が 2014/01/08 となっているので、完成するまでに約 1 年半もかかっているんだね〜。やる気無かったのもあるけど、そもそも Xcode の使い方がわからなかったものね。

アプリケーションとして保存

Xcode 上で実行させることは出来るけれど、単体のアプリケーションとして書き出すにはどうすればよいのだろう?メニューから

Product -> Archive -> Export (Export as a Mac Application)

として保存すればよい。

辞書をどこに置くか

辞書をどうするかの話なのだけど……。実行中のアプリケーションのパスを取得する方法は下記の通り。

自分自身のパス

NSString *path = [ [ NSBundle mainBundle ] bundlePath ];

自分自身の Resource フォルダのパス

NSString *path = [ [ NSBundle mainBundle ] pathForResource:@"hoge" ofType:nil ];

これはグローバル変数に出来ないのかな?

NSString *kanadict = @"/Users/hoge/project/mto/dict/kana-jisyo";

をそのまま

NSString *kanadict = [[NSBundle mainBundle] pathForResource:@"kanji-jisyo" ofType:nil];

に変更しても Xcode に怒られてビルドできないのだけど。

どうやってもダメだ。各インスタンス毎にやれってことかな。CUI 版を見ると各処理ごとにパスを渡すようにしてたわ。仕方ないので同様に IBAction 毎に同じものをコピペして設定することにした。

辞書をアプリケーションに内包する

辞書ファイルへのパスを直書きしているのだけれど、これだと自分のローカル内でしか動かないし、Mac らしくないのでアプリケーション内に内包することにした。

  • Add Files to "CocoaMto"... で kana-jisyo 等をプロジェクトに追加
  • Destination: Copy items if needed にチェック
  • Added folders の Create folder references にチェック

をして取り込むと良いらしい。

再度アプリケーションを書き出して CocoaMto.app/Contents/Resources/ 以下に辞書が入っているのを確認。どこに置いても動く。やった〜!

ただしこうすると、辞書をアップデートする時が面倒になるんだよね。直接 Resources に上書きコピーしても良いのだろうか?

フォントの種類とサイズ

使ってみてデフォルトのウインドウサイズが小さかったので、640x480 から 800x600 にすることにした。ついでなのでテキストエリアも大きくし、ウインドウ自体の拡大縮小(縮小は640x480まで)にも対応することにした。

ウインドウはちょうど良い大きさになったのだけれど、相対的にフォントサイズが小さいような気がしてきた。角ゴチックを丸ゴチックにもしたい。ところが残念なことに (最近の)Text View はフォントの種類や大きさを指定することが出来ないのだとか。

あれこれやっていると、各種 IBAction の処理に下記のような設定を入れておくと、変換後の文字列は指定した通りの種類とサイズで表示されるようになった。

[_resultTextArea setFont:[NSFont fontWithName:@"Hiragino Maru Gothic ProN W4" size:24.0]];

ただ困ったことに、これではアプリケーションを起動して最初に文字列を受け入れる際には効かないんだよね。変換後に反映されるの。

プロジェクトを作成した時に自動的に挿入された applicationDidFinishLaunching を利用してみることにした。英語で「初期化はここでやりなはれ」って書いてあるよね。実際には下記のように入力してみたのだけど変化はなかった。

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application
    [_inputTextArea setFont:[NSFont fontWithName:@"Hiragino Maru Gothic ProN W4" size:24.0]];
    [_resultTextArea setFont:[NSFont fontWithName:@"Hiragino Maru Gothic ProN W4" size:24.0]];
}

いろいろと調べてみると、MainMenu.xib を選択して右ペインの Referencing Outlets から New Referencing Outlet をつつつ〜っと File's Owner のところまで引っぱってやる。delegate ってポップアップされるので接続。こうすることで期待通りの動きになった。

継ぎ接ぎだらけで何とか動いているような感じだけれど、これで Cocoa Mto の作成は一段落としよう。そいういえば変換の速度は JavaScript 版よりもかなり遅いね。

ミス

何度か変換をしていたら、旧字旧仮名から新字新仮名へ変換した際の結果がおかしかった。変換する順番を間違えていたみたいだ。まず先に漢字を変換した後に仮名の変換をしなければいけなかったのだった。

ウインドウを閉じてアプリケーションも終了

このアプリケーションはウインドウが一つしかないので、閉じた時にアプリケーションも終了させたい。下記を記述すれば出来る。

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:
    (NSApplication *)theApplication
{
    return YES;
}

メモリリークとかスタックオーバーフローとか

良くわからんけれども。アクティビティモニタで CococaMto の様子を見てみることにした。起動したばかりの時は 14MB 程度のメモリ使用量。少し長めの文章を何度か置換してみたけど、メモリ使用量は 50 MB 程度で落ち着いていた。メモリリークはしていない感じだけれど、このまま起動し続けてみる。

その後の経過

起動して使い続けてもメモリ使用量はあまり変わりはなく、どんどん増えていくようなこともなかった。

仮名辞書に変更があったので、これをそのまま CocoaMto の Contents/Resources/ 以下に直接 kana-jisyo をコピーしてみた。こうすることにより、プロジェクトをリビルドすることなく語彙をアップデートすることができた。

この記事に続く。