7

読み取り専用プロパティを持つクラスがあると仮定します。

//MyClass.h
@interface MyClass

@property (readonly) NSInteger MonitorMe;

@end

ここで、このプロパティのポイントが、別のオブジェクト内の別のプロパティの変更を監視することであり、プロパティが「監視」されると、他の外部オブジェクトからの値を検査することによって派生値を返すと仮定します。

//MyClass.m
@implementation

@synthesize MonitorMe;
-(NSInteger) getMonitorMe
{
    return globalStaticClass.OtherNSInteger;
}

... Inits and Methods ...
@end

ここで、MyClassオブジェクトのインスタンスを作成し、プロパティにKVOオブザーバーを追加したいとしMonitorMeます。

//AnotherClass.m
@implementation AnotherClass.m

    @synthesize instanceOfMyClass;

    -(id)init
    {
        ...
        instanceOfMyMethod = [MyClass init];
            [MyClass addObserver: self 
                  forKeyPath: @"MonitorMe" 
                     options: NSKeyValuObservingOptionNew
                     context: nil];
        ...
    }

私の質問は、MonitorMeプロパティは外部オブジェクトの値の変更のみを監視するため、値がglobalStaticClass.OtherNSInteger変更されたときにオブザーバーメソッドが実行されるかどうかです。また、答えが「はい」の場合、これはどのように行われますか?

これが機能する場合、私にはコンパイラのブードゥーのように見えます。

ノート

違いはないと思いますが、この実装にはARCを使用しており、iOSデバイス用にコンパイルしています。このタイプの質問では、OS XとiOSの間にコンパイルの違いがあるとは思えませんが、それが重要な場合は、上記のような実装を必要とするiOSプロジェクトがあります。

また、上記の例は、私の実際のニーズの非常に基本的な設定です。globalStaticClass.OtherNSInteger読み取り専用プロパティの代わりに、値に観測値を追加できる/すべきであると主張することができますMonitorMe。私の実際の状況では、読み取り専用プロパティが私の例よりもはるかに複雑であるため、その答えは十分ではありません。

4

1 に答える 1

8

globalStaticClass.OtherNSInteger値が変化したときにオブザーバーメソッドは実行されますか?

いいえ。ただし、 ( 「globalStaticClass」が実際にMyClassのプロパティである場合は、より一般的な方法で)これを実現できます。KVOガイドの「依存キーの登録」を参照してください。+keyPathsForValuesAffectingMonitorMe+keyPathsForValuesAffectingValueForKey:

簡単なモックアップは次のとおりです。

#import <Foundation/Foundation.h>

@interface Monitored : NSObject 
@property NSInteger otherInteger;
@end

@implementation Monitored
@synthesize otherInteger;
@end

@interface Container : NSObject 
@property (readonly) NSInteger monitorMe;
@property (strong) Monitored * theMonitored;

- (void)changeMonitoredInteger;
@end

@implementation Container

@synthesize theMonitored;

+ (NSSet *)keyPathsForValuesAffectingMonitorMe {

    return [NSSet setWithObject:@"theMonitored.otherInteger"];
}

- (id) init {

    self = [super init];
    if( !self ) return nil;

    theMonitored = [[Monitored alloc] init];
    [theMonitored setOtherInteger:25];

    return self;
}

- (NSInteger)monitorMe
{
    return [[self theMonitored] otherInteger];
}

- (void)changeMonitoredInteger {

    [[self theMonitored] setOtherInteger:arc4random()];
}

@end

@interface Observer : NSObject 
@end

@implementation Observer

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

    NSLog(@"Observing change in: %@ %@", keyPath, object);
}

@end

int main(int argc, const char * argv[])
{

    @autoreleasepool {

        Observer * o = [[Observer alloc] init];
        Container * c = [[Container alloc] init];

        [c addObserver:o
            forKeyPath:@"monitorMe"
               options:NSKeyValueObservingOptionNew
               context:NULL];

        [c changeMonitoredInteger];
        [c changeMonitoredInteger];

    }
    return 0;
}

PS Cocoaスタイルの注意:プロパティ/変数には小文字の頭文字を使用する必要があります。(これはARCのため、実際にはより重要になります)アクセサメソッドに「get」で始まる名前を付けないでください。これは、Cocoaでの受け渡しを含む特定の意味を持ちます。バッファと参照によるデータの取得。

于 2012-05-04T20:13:07.520 に答える