KVO not working for class property

I'm trying to understand key value observation in iOS but I think I'm not doing something correctly. As an idea, I tried to add an observer to a view controller's property (a view connected with an IBOutlet). This view (tableIndicator) is animated so I wanted to see if I can get the observer to react when the view's frame changes.

So I did the following, inside the view controller's viewDidLoad:

[tableInidicator addObserver:self forKeyPath:@"frame" options:0 context:nil];

tableIndicator is my view/class property, I'm adding the view controller (self) as the observer, 0 for the default options and frame as the key value being observed.

Then, I'm waiting to see if this function is triggered as the frame changes:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    NSLog(@"value changed");
}

...but nothing happens.

I'm not necessarily looking for fix to this code since it serves no purpose other than for me to understand it and I would be really grateful if someone could point out to me what I'm doing wrong. Some good examples/tutorials would be awesome too.

The ones I found ( http://iphonedevelopment.blogspot.ro/2009/02/kvo-and-iphone-sdk.html / http://nachbaur.com/blog/back-to-basics-using-kvo ) did not cover such cases. They were only observers applied to a class to watch for one of its properties, not for the property of a (custom)object inside a class, something that I think would be more useful for me.

Thank you in advance

[edit] For those who will miss my comment on the accepted answer:

Changing a view's center will apparently not trigger an observer for the frame property. You have to change the frame itself.


Check that your IBOutlet is connected correctly, probably the tableIndicator ivar points to a nil. Consider this simple code below, it works. It just creates a window, add a red square on it, then register using KVO the object to be notified for frame change. Finally it instantiates a button: each time you tap on it the frame is reduced by size, and the notification is triggered correctly (you will see the message in the debug console). So you must check your code.



#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize v = _v;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];

    self.v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
    _v.backgroundColor=[UIColor redColor];
    [self.window addSubview:_v];

    UIButton *b = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    b.frame=CGRectMake(0, 300, 40, 10);
    [b setTitle:@"A" forState:UIControlStateNormal];
    [b addTarget:self action:@selector(changeFrame) forControlEvents:UIControlEventTouchUpInside];
    [_window addSubview:b];

    [_v addObserver:self forKeyPath:@"frame" options:0 context:NULL];

    return YES;
}

-(void)changeFrame {
    CGRect _f = self.v.frame;
    _f = CGRectInset(_f, 20, 20);
    _v.frame=_f;
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    NSLog(@"Observing...");
}

There is something which is not entirely clear about your code. Is tableIndicator a custom class derived from UIView ? The method observeValueForKeyPath should be defined inside that class, and it would be then called. But I am not sure this is the best approach.

In general, a sounder approach is to define your controller (not your view) as an observer. In this case you do:

[self addObserver:self forKeyPath:@"view.frame" options:0 context:nil];

from inside the controller at some point; observeValueForKeyPath would also be defined as a method in the controller.

链接地址: http://www.djcxy.com/p/47344.html

上一篇: 我应该在自定义setter中使用will / didSetValueForKey吗?

下一篇: KVO不适用于集体财产