ヒレガス本 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 に置いておきます。