【问题标题】:KVO not working for class propertyKVO 不适用于类属性
【发布时间】:2012-06-01 07:37:36
【问题描述】:

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

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

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

tableIndicator 是我的视图/类属性,我将视图控制器(自身)添加为观察者,默认选项为 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 属性的观察者。您必须更改框架本身。

【问题讨论】:

  • 据我所知,如果 tableindicator 是您的视图控制器,那么请使用 NSNotification 而不是 KVO
  • 我知道如何使用 NSNotification。我正在尝试为此使用 KVO,以便更好地理解这种技术。
  • 我知道这是一个很久以前就已经回答的老问题了,但为了其他可能找到它的人,我想添加评论。关于 UIKit 中视图的“框架”,您应该意识到它是从“边界”和“中心”中找到的值合成的。如果要对视图的位置或大小进行 KVO,通常最好观察边界或中心,而不是框架属性。如果您直接更改 frame 属性,它只会触发 KVO 通知。

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


【解决方案1】:

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

一般来说,更合理的方法是将您的控制器(而不是您的视图)定义为观察者。在这种情况下,您可以:

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

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

【讨论】:

  • 不,tableIndicator 不是一个类,它是一个简单的 UIView,当我在表格中滚动时它会四处移动。不过,您的观察非常有价值,我实际上想知道如何观察自定义对象的值。不幸的是,应用您的解决方案似乎不起作用,这很奇怪......我什至尝试了一个简单的布尔属性,但我仍然无法得到任何反应。我想我会多读一些,我肯定在这里做错了
【解决方案2】:

检查您的 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...");
}

【讨论】:

  • 我的视图控制器及其视图正在工作,一切都已连接。我试图在完成的项目上实现 KVO 代码,所以问题不存在。我现在看看你的代码,谢谢!
  • 我在一个新项目上尝试了你的代码并且它有效,但不适用于我的项目。不过我确实设法找出了问题,这是因为我基本上是在改变视图的中心,而不是专门改变它的框架。当我强行更改框架时,它起作用了,我收到了通知。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-19
  • 2014-10-06
  • 2012-04-20
  • 2017-03-15
  • 2016-07-16
  • 1970-01-01
相关资源
最近更新 更多