【问题标题】:Value binding on a slider don't update properly滑块上的值绑定未正确更新
【发布时间】:2012-05-17 21:27:16
【问题描述】:

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

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

当我在 UI 中拖动滑块时,会调用正确的设置器,但由于某种原因,当我以编程方式更改值时滑块没有得到更新。 我会说我了解绑定的原理以及 KVC 的工作原理。而且我还知道,当您以编程方式更改值时,您必须使用 getter 或 setter,或者您必须使用 [self willChangeValueForKey:@"theKey"] 和 [self didChangeValueForKey:@"theKey"] 通知观察者。

由于某种原因,这仍然不起作用。 我在 getter 中也有一些日志语句。它甚至没有被调用一次!

我无法真正解释这种行为的原因可能是什么。 唯一的一点是,这与在网上(以及 Aaron Hillegass 的书中)找到的简单示例有点不同的是,我使用的是密钥路径而不是简单的密钥。

我从 IB 转到具有 activeMovie 属性的 App Delegate。 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];
}

【问题讨论】:

  • 关键路径不应该以“self.”开头,但我不知道这是问题所在。显示属性声明,如果未合成,则显示应用程序委托类中的 activeMoveVS_Movie 类中的 moviePosition 的实现。另外,您实际使用的是 setter 还是 -will/DidChangeValueForKey:?如果是后者,请显示执行此操作的代码。位置是否在后台线程上更新?最后,你为什么不使用内置的电影播放器​​/控制器视图?
  • 我正在构建一个专业用途的应用程序。内置的电影播放器​​/控制器视图无法提供我需要的东西。将更新帖子并添加一些代码。

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


【解决方案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* 的设置器。

【讨论】:

  • 我很抱歉。在从 Xcode 复制粘贴代码时,我做了一些小改动,并没有修复试错代码。请检查上面的更新代码。同时,我将在提供的链接上阅读文档。非常感谢!
  • 新代码看起来好多了,但现在我想知道它是否反映了产生你所询问的奇怪行为的情况。也许你无意中解决了这个问题。我现在看到的问题:@synthesize 是多余的,因为您提供了访问器实现。在 getter 名称中有一个反引号 (`)。设置器中的内存管理略有关闭。您不能防止 newPos_moviePosition 相同。您应该在释放_moviePosition 之前保留newPos 或将整个方法用if (newPos != _moviePosition) ... 括起来。
  • 好的,修复了内存错误并删除了@synthesize 指令。感谢您的提示。不幸的是,这并没有改变任何东西。当我使用访问器方法更改代码然后调用 setter 以获取新值时,NSSlider 应该会收到通知,对吗?我只是不明白为什么这不起作用。
  • 您是否有可能拥有两个独立的应用委托类实例?也许一个在 NIB 中实例化,一个在代码中实例化?
  • 没有。但我刚刚意识到,每次打开新电影时,activeMovie 实例都会发生变化。绑定是用KVO建立的,对吧?但是当观察到的对象(关键路径的一个组成部分)发生变化时会发生什么?
猜你喜欢
  • 2019-09-04
  • 2012-06-18
  • 2015-02-20
  • 1970-01-01
  • 2020-06-28
  • 1970-01-01
  • 1970-01-01
  • 2019-09-23
  • 1970-01-01
相关资源
最近更新 更多