KVO不为班级财产工作

时间:2012-06-01 07:37:37

标签: objective-c ios key-value-observing

我正在尝试理解iOS中的键值观察,但我认为我没有正确地做某事。 作为一个想法,我试图将一个观察者添加到视图控制器的属性(与IBOutlet连接的视图)。这个视图(tableIndicator)是动画的,所以我想看看是否可以让观察者在视图的帧发生变化时作出反应。

所以我在视图控制器的viewDidLoad中执行了以下操作:

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

tableIndicator是我的视图/类属性,我将视图控制器(self)添加为观察者,0表示默认选项,框架作为观察到的键值。

然后,我正等着看这个功能是否随着帧的变化而被触发:

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

......但没有任何反应。

我不一定在寻找这个代码的修复程序,因为除了我理解它之外它没有任何意义,如果有人可以向我指出我做错了什么,我将非常感激。一些好的例子/教程也很棒。

我找到的那些(http://iphonedevelopment.blogspot.ro/2009/02/kvo-and-iphone-sdk.html / http://nachbaur.com/blog/back-to-basics-using-kvo)没有涵盖此类案件。他们只是观察者应用于一个类来监视它的一个属性,而不是一个类中的(自定义)对象的属性,我觉得这对我来说更有用。

提前谢谢

[edit] 对于那些会错过我对已接受答案的评论的人:

更改视图的中心显然不会触发frame属性的观察者。你必须改变框架本身。

2 个答案:

答案 0 :(得分:2)

有些内容对您的代码并不完全清楚。 tableIndicator是从UIView派生的自定义类吗?应该在该类中定义方法observeValueForKeyPath,然后调用它。但我不确定这是最好的方法。

通常,更健全的方法是将您的控制器(而不是您的视图)定义为观察者。在这种情况下,您可以:

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

在某个时刻从控制器内部; observeValueForKeyPath也将被定义为控制器中的方法。

答案 1 :(得分:1)

检查您的IBOutlet是否正确连接,可能tableIndicator ivar指向nil。 考虑下面这个简单的代码,它可以工作。它只是创建一个窗口,在其上添加一个红色方块,然后使用KVO注册要通知帧更改的对象。最后它实例化一个按钮:每次点击它时,框架都会缩小,并且通知会被正确触发(您将在调试控制台中看到该消息)。 所以你必须检查你的代码。



#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...");
}