iOS,KVO:Observer无法跟踪对myObject.myCALayer.center的更改

时间:2010-11-24 00:22:52

标签: ios position calayer key-value-observing

我有一个观点。这个视图中间有一个轮子。它还支持iAd和自动旋转。因此,只要广告在顶部弹出,或者设备旋转,轮子就会自动将其自身重新定位到开放空间的中心。

现在我有一个班级来检测用户是否在转动轮子。它来自UIAdvancedGesture,但为了使其正常工作,它需要知道方向盘的中心。这在不断变化。如何解决?

我想'观察'myObject.myCALayer.center,每次更改时,都会将新值发送到我的touchinput-processing类。

所以我这样做了:

- (id) initWithFrame: (CGRect) theFrame
              target: (id) p_target
     actionPlayChord: (SEL) p_actionPlayChord
      actionSettings: (SEL) p_actionSettingsClick
{
    target = p_target;
    actionPlayChord = p_actionPlayChord;

    self = [super initWithFrame: theFrame];

    if ( ! self )
        return nil;

    CGPoint centre = CGPointMake(theFrame.size.width / 2.0, theFrame.size.height / 2.0);

    WheelTouchHandler * wheelTouchHandler = [WheelTouchHandler alloc];
    [wheelTouchHandler initWithTarget: self 
                       activateAction: @selector(engaged:)
                         moveCWAction: @selector(movedCW:)
                        moveACWAction: @selector(movedACW:)
     ] ;

    [self addGestureRecognizer: wheelTouchHandler];

    [self setMultipleTouchEnabled: NO];


    self.wheel = [Wheel alloc];

    NSUserDefaults * prefs = [NSUserDefaults standardUserDefaults];
    NSString *symbol = [prefs stringForKey: @"sharpsOrFlats"];

    [self.wheel init_rMax: WHEEL_R_MAX
                     rMin: WHEEL_R_MIN
                   rGap01: WHEEL_R_RATIO_GAP_TO_DISC
                   rRatio: WHEEL_R_RATIO_OUTER_TO_INNER
              sharpsFlats: symbol
               bitmapSize: theFrame.size 
     ] ;

    [self.layer addSublayer:  [self.wheel wheelLayer] ];

    [self.wheel.wheelLayer setPosition: centre ];


    [self.layer addSublayer:  [self.wheel labelLayer] ];
    [self.wheel.labelLayer setPosition: centre ];

    // "center" fails too...
    [self.wheel.wheelLayer addObserver:self forKeyPath:@"position" options:0 context:nil];


    return self;
}

- (void)observeValueForKeyPath:(NSString *)keyPath 
                      ofObject:(id)object 
                        change:(NSDictionary *)change 
                       context:(void *)context
{
    NSLog(@"Changed!"); <--  this line does not get hit - why?
}

然而,没有记录任何内容。我究竟做错了什么?显然轮子的CALayer会在屏幕上重新定位。但是观察者没有观察到这种变化。怎么解决?

更新:  显然KVO在CALayer属性上存在一些问题。

我尝试过对CALayer进行子类化,如下所示:

@implementation WatchedLayer

+(BOOL) automaticallyNotifiesObserversForKey: (NSString *) key
{

    //, if key is @"position" return YES, otherwise return [super automatically...]

    if ([key isEqual: @"position"])
        return YES; // doesn't get hit

    if ([key isEqual: @"center"])
        return YES; // <-- gets hit

    return [super automaticallyNotifiesObserversForKey: key];
}

- (void) setValue: (id) value 
           forKey: (NSString *) key
{
    // method doesn't get hit


    if ([key isEqual: @"position"])
    {
        NSLog(@"POSHIT");
    }

    [super setValue: value 
             forKey: key];
}

@end

但仍然没有快乐

2 个答案:

答案 0 :(得分:4)

某些CALayer属性不符合KVO标准。例如,CALayer的frame属性似乎是其中一个属性。我已成功观察到对bounds属性(CGRect)的更改,而不是符合KVO(至少在10.6中)。

我还测试了位置属性,它符合KVO 10.6。我不确定10.5和iOS。

似乎CALayer的KVC / KVO兼容属性在10.5和10.6之间存在差异。具体来说,CALayer子类的自定义属性在10.5中似乎不符合KVO,但在10.6中符合要求。在10.5,10.6和iOS之间,CALayer属性之间可能存在其他KVO合规性差异。

http://lists.apple.com/archives/cocoa-dev/2008/Dec/msg01141.html

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/Layers.html%23//apple_ref/doc/uid/TP40006082-SW1

答案 1 :(得分:-2)

我相信你只能观察物体。您要观察的属性是结构。