DocumentBasedApplication
| Table of Contents |
Cocoa Document-based Applicationの作り方(基本)
Xcode 1. ファイル > New Project > Cocoa Document-based Application
Xcode 2. ターゲット > 「名前」ダブルクリック > プロパティ > 拡張子 txt または *
Xcode 3. MyDocument.xib ダブルクリック
InterfaceBuilder (以下IB).
Tools > Library 表示。
NSTextView をウィンドウにドラッグアンドドロップ。
Tools > Inspector > Scroll View Size > Auto sizing でたてよこ設定。ウィンドウリサイズで同時にリサイズするように。
File's owner (これが NSDocument のオブジェクト) 選択 > Comand + 6 (Inspector起動)
Outlet に _textView を追加。
ソースコードに反映
- File > Write Class Files > Merge。
- こわいので手書きもあり。Xcode で MyDocument.h を開き、
IBOutlet NSTextView* _textView;
Ctrl+ドラッグアンドドロップ - File's Owner => TextView画面. _textView の接続。
Xcode 4. ビルドして進行。File > Open でファイル指定はできるが、まだ読みこんだりしてはくれない。
Cocoa Document-based Applicationの作り方(続)
- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
[super windowControllerDidLoadNib:aController];
// Add any code here that needs to be executed once the windowController has loaded the document's window.
// ファイル名の取得
NSURL *fileURL = [self fileURL];
if (! fileURL) {
return;
}
// テキストファイルを読み込みます
NSString *string = [[[NSString alloc] initWithData:[NSData dataWithContentsOfURL:fileURL] encoding:NSUTF8StringEncoding] autorelease];
if (! string) {
return;
}
// テキストビューにテキストを設定します
[_textView setString:string];
}
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
{
// テキストビューからテキストを取得します
NSString* string;
string = [_textView string];
// テキストをNSData型に変換します
NSData* data;
data = [string dataUsingEncoding:NSUTF8StringEncoding];
return data;
// Insert code here to write your document to data of the specified type. If the given outError != NULL, ensure that you set *outError when returning nil.
// You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
// For applications targeted for Panther or earlier systems, you should use the deprecated API -dataRepresentationOfType:. In this case you can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead.
if ( outError != NULL ) {
*outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
}
return nil;
}
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
// Insert code here to read your document from the given data of the specified type. If the given outError != NULL, ensure that you set *outError when returning NO.
// You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead.
// For applications targeted for Panther or earlier systems, you should use the deprecated API -loadDataRepresentation:ofType. In this case you can also choose to override -readFromFile:ofType: or -loadFileWrapperRepresentation:ofType: instead.
if ( outError != NULL ) {
*outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
}
return TRUE;
}
Document-based application に Print 機能
MenuItem.xib を開く。
File > Print メニューを Ctrl+ドラッグアンドドロップ で First Responder にもっていき、print: につなげる。
どこかのクラスの print メソッドが呼ばれる。
このメソッドは現在選択している NSTextView のテキストを印刷してくれるらしい。
Document-based application の New/Open/Close 動作のすげかえ
おそらく別の手段もあるが、一番単純な方法として、 InterfaceBuilder から File > Open メニューを別のメソッド(Action)にすげかえてやればよい。 Close メニューは同様にすげかえられるが、Window 左上の Close ボタンに Action をつけられないので、 Responder chain の仕組みを利用してすげかえる。
あえて Document-based application をシングルウィンドウアプリのように動作させる方法。
MyDocument.h
- (IBAction)openFile:(id)sender; // 名前は適当にきめて、つなぐ - (IBAction)newFile:(id)sender; // 名前は適当にきめて、つなぐ - (void)windowWillClose:(NSNotification *)notification; // レスポンダチェインなので名前固定
MyDocument.m
- (IBAction)newFile:(id)sender
{
// テキストビューにテキストを設定します
[_textView setString:@""];
[_mainWindow setTitle:@"Untitled"];
}
- (IBAction)openFile:(id)sender
{
NSOpenPanel *sheet = [ NSOpenPanel openPanel ];
//int returnCode = [ sheet runModalForTypes: [ NSArray arrayWithObjects: @"txt", nil ] ];
int returnCode = [ sheet runModalForTypes: nil ];
if (returnCode != NSOKButton) return;
// ファイル名の取得
NSString *filename = [sheet filename];
NSURL *fileURL = [NSURL fileURLWithPath: filename];
if (! fileURL) {
return;
}
// テキストファイルを読み込みます
NSString *string = [[[NSString alloc] initWithData:[NSData dataWithContentsOfURL:fileURL] encoding:NSUTF8StringEncoding] autorelease];
if (! string) {
return;
}
// テキストビューにテキストを設定します
[_textView setString:string];
// Windows のタイトルを設定します
[_mainWindow setTitle:[filename lastPathComponent]];
//- (IBAction)openFile:(id)sender
//{
// NSOpenPanel *panel = [NSOpenPanel openPanel];
// [panel beginSheetForDirectory:nil
// file:nil
// types:[NSArray arrayWithObjects:@".txt", nil]
// modalForWindow:mainWindow
// modalDelegate:self
// didEndSelector:@selector(openFileDidEnd:returnCode:contextInfo:)
// contextInfo:nil];
//}
//
//- (void)openFileDidEnd:(NSOpenPanel*)sheet returnCode:(int)returnCode contextInfo:(void*)contextInfo
//{
// if (returnCode != NSOKButton) return;
// // NSLog(@"FILES:%@",[sheet filename]);
// [self setFileURL:[NSURL URLWithString:[sheet filename]]];
//}
}
// delegate
- (void)windowWillClose:(NSNotification *)notification
{
//[super windowWillClose:notification];
// [NSApp termininate:nil] が window を閉じようとするため、もう一度 windowWillClose を呼ぶ。
// 2度目の windowWillClose: で呼ばれないようにデリゲート役を降りておく。
[[notification object] setDelegate:nil];
[NSApp terminate:nil];
}
