ページ

ラベル NSViewController の投稿を表示しています。 すべての投稿を表示
ラベル NSViewController の投稿を表示しています。 すべての投稿を表示

2009年11月20日金曜日

NSViewController (2) - Nibから読み込む

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(前回)Cocoaの日々: NSViewController

リファレンスによれば NSViewController は通常 nibファイルから読み込まれるとある。

An NSViewController object manages a view, typically loaded from a nib file.

Mac Dev Center: NSViewController Class Reference

前回紹介したサンプルもだいたいそんなかんじだった。前回のコードを変更して試してみよう。


nibファイルの作成

新しく空の nibファイル を作成する。

前回作ったカスタムビューをコピーする。

File's Owner のクラスを(同じく前回用意した)ViewController に設定する。

イメージとテキストフィールドの Bindings の Value を File's Owner の representedObject へバインドする。

File's Owner の接続はこんな感じ。

nib 経由の NSViewController 作成

前回アウトレット経由で取得していた ViewController へのリファレンスを、nib経由に変更する。追加したのは1行だけ(太字)。

AppController.m

@implementation AppController

- (void)awakeFromNib
{
imageFile = [[ImageFile alloc] init];
imageFile.image = [NSImage imageNamed:@"sample"];
imageFile.name = @"sample.jpg";
imageFile.date = [NSDate date];

viewController = [[NSViewController alloc]
initWithNibName:@"SampleView" bundle:nil];
[viewController setRepresentedObject:imageFile];
[view addSubview:[viewController view]];
}

@end


これだけOK。

実行してみよう。

出た。

ソースコード

githubからどうぞ
xcatsan's SampleCode at 2009ViewControllerStudy at 20091120 from xcatsan's SampleCode - GitHub1120 - GitHub


考察

イメージを描いてみた。

こうすると NSViewController の役割が(多分)よくわかる。

NSViewController は View と Model の間を取り持つ役割を果たしている。View から見るとModelの実装が隠されていて、表示に必要な情報を得るには(あるいは保存するには) NSViewController が提供する representedObject だけを見れば(bind)良い。言い換えると開発時にViewの制作者はModelの実装を知る必要ことなくコントロールを配置や設定に専念することができる。お互いに実装が隠されることで Model の変更が View へ与える影響は少なく、その逆の場合も影響は少ない。

また nib に NSViewController を入れることでコンポーネント的な扱いができるようにもなる。複数並べたり、別のプロジェクトでも使い回せるということ。利用する側は nib を読み込み reprsentedObject と Model を紐づけるだけで良い。一旦紐づければ後は Cocoa bindings が働いて、コードを書かなくとも View と Model の同期が自動的に行われる。NSCollectionView ではまさに NSCollectionViewItem(NSViewControllerのサブクラス)をこの目的で使っている。

試しに先ほどのサンプルに手を加え NSViewController を複数作成して配置してみた。これを発展させれば NSCollectionView のようなものが作れるだろう。
#ただ大量にビューを並べると様々なリソースを食い過ぎるので工夫が必要だと思われる。



複数並べた版のソースコード:
ViewControllerStudy at 20091120-2 from xcatsan's SampleCode - GitHub

2009年11月19日木曜日

NSViewController

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

NSViewController は Mac OS X 10.5 から導入されたクラスで名前の通りビューを対象としたコントローラ。テーブルビューのカスタマイズを調査する過程で気になったので少し調べてみた。

Mac Dev Center: NSViewController Class Reference

NSViewController

リファレンスから説明を転載する。




An NSViewController object manages a view, typically loaded from a nib file.
This management includes:
  • Memory management of top-level objects similar to that of the NSWindowController class, taking the same care to prevent reference cycles when controls are bound to the nib file's owner that NSWindowController began taking in Mac OS v 10.4.
  • Declaring a generic representedObject property, to make it easy to establish bindings in the nib to an object that isn't yet known at nib-loading time or readily available to the code that's doing the nib loading.
  • Implementing the key-value binding NSEditor informal protocol, so that applications usingNSViewController can easily make bound controls in the views commit or discard the changes the user is making.

ポイントは3つある。一つ目は NSWindowController 同様にメモリ管理する役割。ただ見るところ管理というほど大げさではなく、実際はモデルとビューのリファレンスを持っているということか。

2つ目はそのリファレンスの一つでモデルへの参照 representedObject を持っているということ。これは後ほど紹介するが Interface Builder で Cocoa bindings を使う時のパスの一部として使える。

3つ目は非形式プロトコル NSEditor を実装していること。

使った事が無いので推測になるが、変更点の確定や破棄(アンドゥ)が行えるようだ。


NSViewController が無くてもアプリは作れるが、MVC で構成する際にこれまでの経験からよく使われるだろう機能をコントローラーとしてまとめたクラスだといえる。


ADC提供のサンプル

NSViewController を使ったサンプルが ADCからいくつか提供されている。

プルダウンから NSViewController を切り替えるサンプル。それぞれのタイプ(Image, Table, Video, iSight Camera)毎に NSViewController およびそれを含む Nibファイルが用意されている。


メインは NSCollectionView。


自作サンプル

NSViewContorller をつかったサンプルプログラムを試しに作ってみる。

まずは Cocoa Application のプロジェクトを作り、毎度おなじみの AppController クラスを用意しておく。

AppController.h

@class ImageFile;
@interface AppController : NSObject {

IBOutlet NSView* view;
IBOutlet NSViewController* viewController;

ImageFile* imageFile;
}

@end


ImageFile は表示内容を保持するモデルクラス。

ImageFile.h

@interface ImageFile : NSObject {

NSImage* image;
NSString* name;
NSDate* date;
}
@property (retain, nonatomic) NSImage* image;
@property (retain, nonatomic) NSString* name;
@property (retain, nonatomic) NSDate* date;

@end


次にInterface Builder を立ち上げる。メインウィンドウには Custom View を一つ貼付けておく。

それとは別に Custom View を一つ用意する。ここへ NSImageView と2つのラベルを貼付けておく。


さらに View Controller と AppController もインスタンス化し、必要なアウトレットを接続しておく。
構成はこんな感じになる。

View Controller の接続状況。

Custome View の画像とラベルの Bindings を設定する。Bind先を View Controller として、Model Key Path に representedObject.[ImageFileのプロパティ名]としておく。これだけで View Controller を介してモデルの内容が表示される。

NSViewController の representedObject とモデル(ImageFile)との紐付けおよび、メインウィンドウへのビューの追加は AppController で行う。

AppController.m

#import "AppController.h"
#import "ImageFile.h"

@implementation AppController

- (void)awakeFromNib
{
imageFile = [[ImageFile alloc] init];
imageFile.image = [NSImage imageNamed:@"sample"];
imageFile.name = @"sample.jpg";
imageFile.date = [NSDate date];

[viewController setRepresentedObject:imageFile];
[view addSubview:[viewController view]];
}

@end

テスト用にモデルのインスタンスを一つ用意した。画像はあらかじめ Resources フォルダへコピーしてある。


さて動かしてみよう。

出た。
...検証目的なのでこれといって役に立つものではない。


ソースコード

GitHubよりどうぞ。
ViewControllerStudy at 20091119 from xcatsan's SampleCode - GitHub


NSCollectionView

NSCollectionView も NSViewController を使った例の一つといえる。NSCollectionView で使う NSCollectionViewItem はずばり NSViewController から派生している。

Mac Dev Center: Collection View Programming Guide: Quick Start for Collection Views

Mac Dev Center: NSCollectionView Class Reference
Mac Dev Center: NSCollectionViewItem Class Reference

過去に NSCollectionView の解説をしているので興味の有る方はどうぞ。
Cocoaの日々: NSCollectionView

クラス相関図(もどき)
study01-2.png (image)