関東62回Cocoa勉強会の資料(10/19)

19日に行うCocoa勉強会の資料です。

multiWindow.pdf.

SampleCodes.zip.

内容は、Cocoaでマルチウインドウアプリケーションを作る時のコツみたいな事や考え方をダラダラ説明。

トーマス的な何か

../../../_images/IMG_0876.png

薄暗い中に、突然コレを見て久しぶりに動揺した。

ヒレガス本 18章 課題 続き

bindigのやり方が間違っている気がして、色々とやってみた。

カスタムViewをbinding対応にするやり方は、Appleのサンプルコードや詳解Objective-C2.0第三版で説明されていますが、個人的にはこれは何か違う気がしたのでパス。

まず、先日の「NSControllerが仲介して逆方向への伝播の設定を行っている」は私の間違い。NSControllerは逆方向への伝播は行っていない。

次に、[NSObject infoForBinding:]を使ってやってみた。 コードは、以下のような感じでovalが変更される部分で逆方向にKVCしてるだけ。

- (void) setOval:(NSRect)inOval
{
    if( !NSEqualRects(_oval, inOval) )
    {
        _oval = inOval;

        // binding元への伝播
        NSDictionary* theInfo = [self infoForBinding:@"oval"];

        if( theInfo )
        {
            NSString* thePath   = [theInfo valueForKey:NSObservedKeyPathKey];
            NSString* theObject = [theInfo valueForKey:NSObservedObjectKey];

            [theObject setValue:[NSValue valueWithRect:_oval]
                     forKeyPath:thePath];
        }


        [self setNeedsDisplay:YES];
    }
}

2重にbindingするよりも、「正しい」感じがする。

次に、先日も取り上げた Implementing Your Own Cocoa Bindings を参考にしてコードを書くと、

- (void) setOval:(NSRect)inOval
{
    if( !NSEqualRects(_oval, inOval) )
    {
        _oval = inOval;

        // binding元への伝播
        [self propagateValue:[NSValue valueWithRect:_oval]
                  forBinding:@"oval"];

        [self setNeedsDisplay:YES];
    }
}

ここまで、キレイに書ける。

プロジェクトファイルは、 OvalDoc_2.zipOvalDoc_3.zip に置いておきます。

ヒレガス本 18章 課題

18章で作成したアプリケーションを元に以下の3つの機能を入れるとの事。

  • ドキュメントベースにする
  • ファイルの保存と再生に対応する
  • Undo/Redoに対応する

上記3つは簡単だった。 ハマったのは、viewとdocumentのデータを同期するのにbindingを使った所。

IBを使って操作していると、bind:toObject:withKeyPath:options:1行呼出すだけで双方向にデータを同期してくれると勘違いしていた。

双方向にデータをやり取りするには、それぞれにbind:toObject:withKeyPath:options:を呼出す必要があった。

IB上ではおそらくNSControllerが仲介して逆方向への伝播の設定を行っているのだと思われる。

コード上で行うには、今後は Implementing Your Own Cocoa Bindings を参考にして

[NSObject propagateValue:(id)value forBinding:(NSString*)binding];

を使うとよいかもです。

プロジェクトファイルは、 OvalDoc.zip に置いておきます。