2

KVOについて少し助けが必要です、私はそこの半分くらいです。私がやろうとしているのは、TreeControllerの何かが変更されたときにメソッドをトリガーすることです。

したがって、私はこのコードを使用してKVOとして登録しています。

[theObject addObserver: self
            forKeyPath: @"myKeyPath"
               options: NSKeyValueObservingOptionNew
               context: NULL];

しかし、観察しているキーパスが変更されたときにメソッドをトリガーするにはどうすればよいですか?

もう1つの質問ですが、自分自身をオブザーバーとして追加するときに、キーパスをコアデータモデルのプロパティにしたいのですが、正しく実行しましたか?

4

4 に答える 4

6

オーバーライドobserveValueForKeyPath:ofObject:change:context:して、呼び出したいメソッドをディスパッチします。

@interface Foo : NSObject {
    NSDictionary *dispatch;
    ...
}
@end
@implementation Foo
-(id)init {
    if (self = [super init]) {
        dispatch = [[NSDictionary dictionaryWithObjectsAndKeys:NSStringFromSelector(@selector(somethingHappenedTo:with:)),@"myKeyPath",...,nil] retain];
        ...
    }
}
...
- (void)observeValueForKeyPath:(NSString *)keyPath
            ofObject:(id)object
            change:(NSDictionary *)change
            context:(void *)context
{
    SEL msg = NSSelectorFromString([dispatch objectForKey:keyPath]);
    if (msg) {
        [self performSelector:msg withObject:object withObject:keyPath];
    }
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
...

詳細については、「変更通知の受信」を参照してください。

于 2009-10-02T16:16:55.100 に答える
5

Google ToolboxForMacのGTMNSObject+KeyValueObserving.hカテゴリ、または少なくともそれを刺激したMichaelAshによるブログ投稿をご覧になることをお勧めします。基本的に、手動でKVOを正しく実行することは非常に微妙であり、APIによって提案されるパターンは理想的ではありません。APIに他のレイヤーを配置することをお勧めします(GTMNSObject + KeyValueObservingのように)。これにより、NSNotificationAPIのようになり、微妙なバグの原因の一部が隠されます。

GTMNSObject + KeyValueObservingを使用すると、次のようになります。

[theObject gtm_addObserver:self
                forKeyPath:@"myKeyPath"
                  selector:@selector(myCallbackSelector:)
                  userInfo:nil
                   options:NSKeyValueObservingOptionNew];

の値がタイプの引数で変更されると、あなた-myCallbackSelector:が呼び出されます。これは、必要になる可能性のあるすべての関連情報をカプセル化します。@"myKeyPath"GTMKeyValueChangeNotification

このように、大きなディスパッチテーブルを用意する必要はありません(実際には、カテゴリによって1つが維持されます)。または、スーパー/サブクラスなどとの競合を回避するためにポインタをobserveValueForKeyPath:ofObject:change:context使用する正しい方法について心配する必要はありません。context

于 2009-10-02T16:37:36.273 に答える
4

これを実装する必要があります。これは、キーパスが変更されたときに呼び出されます。

 (void)observeValueForKeyPath:(NSString *)keyPath
                     ofObject:(id)object
                       change:(NSDictionary *)change
                      context:(void *)context;

詳細はこちら

于 2009-10-02T16:16:13.820 に答える
3

(これは私がここで学んだテクニックです:http://www.bit-101.com/blog/?p = 1999

次のように、「コンテキスト」でメソッドを渡すことができます。

[theObject addObserver:self 
            forKeyPath:@"myKeyPath"
               options:NSKeyValueObservingOptionNew
               context:@selector(doSomething)];

..次に、observeValueForKeyPathメソッドで、それをSELセレクタータイプにキャストしてから実行します。

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    SEL selector = (SEL)context;
    [self performSelector:selector];
}

doSomethingメソッドにデータを渡したい場合は、次のように「change」ディクショナリの「new」キーを使用できます。

[theObject addObserver:self 
              forKeyPath:@"myKeyPath"
                 options:NSKeyValueObservingOptionNew
                 context:@selector(doSomething:)]; // note the colon

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
        SEL selector = (SEL)context;

        // send the new value of observed keyPath to the method
        [self performSelector:selector withObject:[change valueForKey:@"new"]]; 
    }


-(void)doSomething:(NSString *)newString // assuming it's a string
{
      label.text = newString;
}
于 2010-08-13T12:32:03.630 に答える