2010-12-02

設定変更を通知する - 環境設定パネルを作る #4 (MacBloggerGlass)

今回の記事の内容は、環境設定パネルで Blog ID を保存したときに(「Save」ボタンを押す)、アプリウィンドウに表示されているブログ一覧が変更された ID のものに自動的に変わるようにするための実装について。このような動作を実装する意図については、前回の記事(→「次は NSNotification に取り組む」)を参照してもらいたい。

変更点

実装の手順は以下の 4 つ。

  • (a) 通知の名前を文字列定数として定義する。
  • (b) 通知を送るオブジェクトで、通知を送るコードを追加する。
  • (c) 通知を受けるオブジェクトで、通知を処理するメソッド(通知ハンドラ)を定義する。
  • (d) 通知を受けるオブジェクトで、監視の登録のためのコードを追加する。
  • (e) 通知を受けるオブジェクトで、監視の登録解除のためのコードを追加する。

(a) はどこで定義しても構わないが、(b) と同じく通知を送るオブジェクトと一緒に定義する方が良いだろう。通知を受けるオブジェクトでは、送るオブジェクト(のクラス)のインタフェース部を #import することになる。

MacBloggerGlass の場合、通知を送るのが PreferenceController で、受けるのが AppController になる。

(b) の通知を送るタイミングは、環境設定パネルで「Save」ボタンが押されたとき。つまり、ボタンに対応するアクションメソッド内になる。

監視の登録 (d) については、少なくとも最初に環境設定パネルが開くより前でなければならない。確実なのは AppController が作られたときだ。AppController はアプリの MainMenu.xib にインスタンスとして登録されているから、アプリが起動した後は NIB がロードされる中で生成(というか復元)される。このタイミングは awakeFromNib で拾うことができる。一般にアプリの起動時に生成(初期化)されるオブジェクトなら init で登録すれば良い(ヒレガス本 Chapter 14 の例はこちらになっている)。また、登録の解除 (e) は dealloc で行う(これはヒレガス本の例と同じ)

実装

PreferenceController
インタフェース部: PreferenceController.h

追加したのは 1 行。クラスのインタフェースにふくまれるものではないので @interface {...} の外側に置かなければならない。こういう定数が増えたら、定数だけを独立させて別ファイルにすべきかも。

extern NSString * const MBGBlogIDChangeNotification;
実装部: PreferenceController.m

ヒレガス本からそのまま引き写し。

- (IBAction)saveSettings:(id)sender
{
    [...snip...]
    // send notification
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    NSDictionary *userInfo = [NSDictionary dictionaryWithObject:selectedBlog.blogID forKey:@"blogID"];
    [nc postNotificationName:MBGBlogIDChangeNotification
                      object:self
                    userInfo:userInfo];
    NSLog(@"Post notification with userInfo (%@)", userInfo);

    [self close];
}
AppController
実装部: AppController.m

通知ハンドラ handleBlogIDChange: は AppController.m だけから参照できる AppController のプライベートメソッドとした(ファイルローカルメソッドと呼ぶべきか?)。これについては荻原(2.0)本の「CHAPTER 09 カテゴリ」を参照のこと。

fetchPosts は GData クライアントライブラリを使って記事のフィードをリクエストするもの。これまで getFeed: というアクションメソッドの一部だったものを今回独立させた。これは、getFeed: と通知ハンドラの両方から呼べるようにするため。もっとも、今回の変更にあわせて、メインウィンドウから Blog ID を入力するフィールドと記事一覧を取得するためのボタンを取り除いたため、getFeed: は無用になってしまったが。

@interface AppController (PrivateMethods)
- (GDataServiceBase *)bloggerService;
- (void)fetchPosts;
- (void)renderHTML:(NSString *)content withBaseURL:(NSString *)baseURL;
- (void)handleBlogIDChange:(NSNotification *)note;
@end

@implementation AppController
[...snip...]
- (void)awakeFromNib
{
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self selector:@selector(handleBlogIDChange:) name:MBGBlogIDChangeNotification object:nil];
}
@end

@implementation AppController (PrivateMethods)
[...snip...]
- (void)handleBlogIDChange:(NSNotification *)note
{
    NSLog(@"Received notification: %@", note);
    blogID = [[note userInfo] objectForKey:@"blogID"];

    [posts removeAllObjects];
    [self fetchPosts];
}
@end

プロトタイプ #0

右のスクリーンショットが今の MacBloggerGlass でこのブログを表示させた様子だ。NSSplitView を使い、上半分で記事一覧、下半分でその内容を表示させている。記事の表示には WebView に対して、取得した記事のフィードのコンテンツをただ文字列として流し込んでいるだけ。つまり、HTML としてきちんとしたドキュメントの構造になっていないし、もちろんスタイルシートや JavaScript も付いていない。ま、GData クライアントライブラリを使った RSS リーダのサンプルアプリといったところか。

今回のプロトタイプでは Blog ID の選択を環境設定に押し込めている。これは、ブログは高々 1 つしか見ることはないし、Blog ID を切り替える頻度は高くない、と想定したから。実際に動かしてみて思うことは、複数のブログを作っているなら他のブログも同時に見たいと思うかもしれない、ということ。つまりは、ブラウザのようにタブやウィンドウで複数のコンテンツを同時に開ける方が良いかもしれない。

ま、それは 1 つのブログをきちんと表示できるようになってから考えよう。せめて、GAE 版と同等の表示ができるようにしてからだ。

おまけ

予告(→「次は NSNotification に取り組む」)では「通知」に関連するドキュメントも探すと書いたが、時間切れで本当に探すだけになってしまった。まだ読めていない。リンクだけは「関連リンク」のところに挙げておく。

また、「通知」に関して書かれたドキュメントを検索していて便利そうなものを見つけた。Devpedia シリーズとでも呼べば良いのかな(URL の一部になっている)。右のスクリーンショットはそれを Safari で開いたところだ。

何が便利かと言うと、たとえば「Cocoa Core Competencies」なら、Cocoa アプリを作るために必要になるさまざまなトピックを一覧できること。また、それぞれについての簡単な説明(使い方をふくむ)が付いていて、より詳しいドキュメントへのリンクもある。ヒレガス本のように、アプリの作り方を順を追って説明するようなタイプのものではないが、実際にアプリを作るときにドキュメントを参照する出発点として役に立ちそう。

検索して見つかったのは以下の 3 つ。

参考文献

詳解 Objective-C 2.0
荻原 剛志
ソフトバンククリエイティブ ( 2008-05-28 )
ISBN: 9784797346800
Cocoa Programming for Mac OS X
Aaron Hillegass
Addison-Wesley Professional ( 2008-05-15 )
ISBN: 9780321503619

関連リンク

関連記事

0 件のコメント:

コメントを投稿