設定を User Defaults に書き込むことは難しくない。設定値が NSString であるならなおさらだ。PreferenceController の実装部に以下のようなコードを埋め込むだけだ。
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *accountID = [accountField stringValue]; [defaults setObject:accountID forKey:@"AccountID"];
また参照する側 (AppController) では、以下のようにすれば良い。
blogID = [blogIdField stringValue]; if ([blogID length] == 0) { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; blogID = [defaults objectForKey:@"blogID"]; }
今回の記事の内容は、設定を保存するコードではなく、設定の保存を中心としたユーザ体験上の問題について。
UI が提供するユーザ体験は、実際に動かしてみると、デザイン段階での「あら」があちこちに浮かび上がってくる。環境設定パネルでもアプリ本体とつないで見ると、いくつかの不備が見えてきた。今日、「Save」ボタンの機能を実装してみて、(そして動かしてみて)以下の 3 点について気付いた。
- パスワードを User Defaults に保存するのはマズい。
- 「Save」ボタンを押した後のフィードバックがない。
- ブログのリストと選択の状態が保存、復元されない。
設定を保存すると ~/Library/Preferences に置かれるファイルに書き込まれる。テキスト形式は言うに及ばず、バイナリ形式にしても、そこにパスワードを平文で書き込むのはマズい。パスワードを保存する場合には、キーチェーンと連携させるのが Mac アプリの作法だろう。とりあえず、パスワードは保存の対象から外しておく。キーチェーンとの連携は棚上げ。
アプリを使う際にさまざまな処理の結果がユーザに対して適切にフィードバックされるかどうかはユーザ体験に大きく影響する。「ボタンを押す」というユーザのアクションに対してユーザの目に見える反応が何も起こらないと、ユーザに不安を感じさせることになる。ありがちなフィードバックとしては「完了しましたダイアログ」を出すことだが、これは使いどころを間違えると、ただわずらわしいだけになる。
今回の環境設定パネルの場合、「Save」が押されたらパネル自体を消すというのが良いように思う。現状ではこのパネルの役割はアプリのメインウィンドウで表示するブログの選択のみだ。そこで「Save」ボタンが押されたのだから、保存処理が完了したのなら何も仕事は残っていない。だから、パネルを消せば処理が(成功のうちに)完了したことは十分に伝わるし、(わずらわしいダイアログのような)余分な UI も増えない。
今、悩んでいるのは、最後の環境設定パネルを(設定を保存し)一度閉じて再び開いたときに、元の状態を復元させる仕組みだ。必要な情報はブログ(タイトル)の一覧と選択された項目へのインデックス。ここで、問題が 2 つほど出てくる。
1 つは、「ブログ(タイトル)の一覧の保存」に関係する。前回の記事(→「表示するブログの選択」)で書いたように、環境設定パネル(右図)の表部分 (NSTableView) は、Cocoa Bindings によって(NSObjectController と NSArrayController を介して)モデルのプロパティに結びついている。表に出てくる項目は EntryBlog のプロパティであり、これを保存することは EntryBlog を保存することになる。Cocoa Bindings で結びついている以上、ブログのタイトルだけを NSStrings を抱えた NSMutableArray として保存しても意味はない。
そう、1 つ目の問題は環境設定パネルにとってのモデルである FeedBlog と EntryBlog の保存(永続化)の仕組みが必要だ、というものだ。
2 つ目の問題は、選択の状態をどうやって復元するか、というもの。何度も書いているようにパネルの表(ビュー)は Cocoa Bindings によってモデルと結びついている。だから、その選択の状態も Cocoa Bindings でどこかの何かと結びつけなければならない。Interface Builder で NSTableView の Bindings パネルを開くと Selection Indexes という「結びつき」を設定する項目がある。これを使えば選択の状態を Cocoa Bindings による結びつきで伝えられそうなんだが、問題はそれを「どこ」の「何」というプロパティにするか。
保存すべき情報という意味でこれもモデルの一部と言える。FeedBlog の一部にすることもできるが、抽象化の障壁に穴を空けてしまうようでイヤな感じだ。別のモデルオブジェクトとして独立させた方が良い。と言っても、情報自体は整数値 1 つなので、実際には PreferenceController に int のプロパティを増やすことになるか。
次回は表項目の「選択」のための結びつきを Cocoa Bindings で作ることを試してみよう。
まあ、ユーザ体験うんぬん以前に、ウィンドウの UI を考えるときに状態の保存と復元について考えていないのがそもそも悪い。経験不足だと切って捨ててしまえばそれまでだけど、Cocoa Bindings を使ってモデルとビューを同期させることに注意が引きつけられていたせいもあるだろう。
0 件のコメント:
コメントを投稿