滑块上的值绑定无法正确更新

时间:2012-05-17 21:27:17

标签: objective-c cocoa cocoa-bindings key-value-observing key-value-coding

我目前正在使用的应用程序是使用普通的NSSlider控制QuickTime影片中的位置。就像在那里的每个媒体播放器一样。

我想将滑块的值绑定到影片位置(在0到1范围内)以避免粘滞/粘合代码。

当我在UI中拖动滑块时,会调用右侧的setter,但由于某种原因,当我以编程方式更改值时滑块不会更新。 我会说我理解绑定的原则以及KVC的工作原理。而且我也知道你必须要么使用getter或setter,要么以编程方式更改值时,必须用[self willChangeValueForKey:@“theKey”]和[self didChangeValueForKey:@“theKey”]通知观察者。

由于某些原因,这仍然无效。 我在getter中也有一些日志语句。它甚至没有被召唤一次!

我无法真正解释自己这种行为的原因是什么。 与网上发现的简单例子(以及Aaron Hillegass的书中)有一点不同的是,我使用的是关键路径,而不是简单的密钥。

从IB,我转到App Delegate,它有一个activeMovie属性。 activeMovie是VS_Movie类的一个实例,它有一个moviePosition属性。所以我的关键路径是:self.activeMovie.movi​​ePosition,Xcode似乎也找到了。

如能提供任何提示和帮助,我将不胜感激! 提前致谢

以下是我正在使用的一些代码:

1。财产申报

// ivar
NSNumber* _moviePosition;

// Property
@property (retain) NSNumber* moviePosition;

2。 Getter和setter实现

- (NSNumber*) moviePosition
{
    NSLog(@"MoviePosition returned : %lf", [_moviePosition doubleValue]);
    return _moviePosition;
}

- (void) setMoviePosition:(NSNumber*)newPos
{
    NSLog(@"New MoviePosition : %lf", [newPos doubleValue]);

    if ( _moviePosition && [newPos isEqualToNumber:_moviePosition] )
        return;

    if ( _moviePosition ) 
       [_moviePosition release];

    _moviePosition = [newPos retain];

    if ( _positioningReady )
    {
        _positioningReady = NO;

        TimeValue newMovieTime = (TimeValue)([_moviePosition doubleValue] * 
                                             (double)_clipDurationTimeValue);
        SetMovieTimeValue(_qtMovie, newMovieTime);
        [_movieView displayCurrentFrameOfMovie:self];

        // Post a notification to inform the observing 
        // classes so they can do the neccessary handling.
        NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
        [nc postNotificationName:VS_MoviePositionChangedNotification 
                      object:self];
    }
}

3。调用函数

- (void) setTimeValue:(TimeValue) value withTimeScale:(TimeScale) scale
{
    SetMovieTimeValue(_qtMovie, value);
    SetMovieTimeScale(_qtMovie, scale);

    double newMoviePosition = (double)GetMovieTime(_qtMovie, NULL) / (double)_clipDurationTimeValue;
    [self setMoviePosition:[NSNumber numberWithDouble:newMoviePosition]];

    [_movieView displayCurrentFrameOfMovie:self];
}

1 个答案:

答案 0 :(得分:1)

鉴于该属性被称为moviePosition,getter应该被称为-moviePosition(没有下划线),并且应该将setter称为-setMoviePosition:(没有下划线和属性的第一个字母)名字大写)。

您没有显示@property声明。虽然允许指定setter和getter的名称,但KVC和KVO都不会注意这一点。对于他们来说,它需要遵循命名约定。请参阅Key-Value Coding Programming Guide: Accessor Search Patterns for Simple Attributes

你确定正如你所声称的那样召集了正确的二传手吗?因为您错误地命名了访问器方法,所以编译器不会识别它们。因此,@synthesize正在生成正确命名的那些。这些都是由KVC引用的(并被KVO迷住)。

这也是-setTimeValue:withTimeScale:调用[self setMoviePosition:newMoviePosition]的原因,这与您的-set_moviePosition:方法不符。但是,您应该收到警告(并且在运行时发生崩溃),因为您将double传递给期望NSNumber*的setter。