Значение привязки на слайдере не обновляется должным образом

Приложение, которым я сейчас работаю, контролирует положение в фильме QuickTime с помощью обычного NSSlider. Как и в любом медиаплеере.

Я хотел привязать значение ползунка к позиции фильма (которая находится в диапазоне от 0 до 1), чтобы избежать липкого / склеенного кода.

Когда я перетаскиваю ползунок в пользовательском интерфейсе, вызывается правильный установщик, но по какой-то причине ползунок не обновляется при программном изменении значения. Я бы сказал, что я понимаю принципы привязки и то, как работает KVC. И я также знаю, что вы должны либо использовать геттеры, либо сеттеры или уведомлять наблюдателей с помощью [self willChangeValueForKey:@"theKey"] и [self didChangeValueForKey:@"theKey"] при программном изменении значений.

По какой-то причине это все еще не работает. У меня также есть несколько операторов журнала в геттере. Это даже не называется один раз!

Я не могу действительно объяснить себе, в чем может быть причина такого поведения. Единственное, что немного отличается от простых примеров, найденных в Интернете (и в книге Аарона Хиллегаса), заключается в том, что я использую ключевой путь вместо простого ключа.

От IB я перехожу к App Delegate, у которого есть свойство activeMovie. ActiveMovie является экземпляром класса VS_Movie, который имеет свойство moviePosition. Итак, мой ключевой путь: self.activeMovie.moviePosition, который Xcode, похоже, тоже находит.

Буду благодарен за любые советы и предоставленную помощь! заранее спасибо

Вот код, который я использую:

1. Объявление недвижимости

// ivar
NSNumber* _moviePosition;

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

2. Реализация метода получения и установки

- (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 ответ

Решение

Учитывая, что свойство называется moviePosition, геттер должен называться -moviePosition (без подчеркивания) и сеттер должен быть вызван -setMoviePosition: (без подчеркивания и первая буква названия объекта пишется с большой буквы).

Вы не показали @property декларация. Хотя разрешено указывать имена установщика и получателя, ни KVC, ни KVO не обращают на это внимание. Для них это должно следовать соглашениям об именах. См. Руководство по программированию кодирования значения ключа: шаблоны поиска аксессоров для простых атрибутов.

Вы уверены, что правильный сеттер вызывается, как вы утверждаете? Поскольку вы неправильно назвали свои методы доступа, компилятор не распознает их как таковые. Следовательно @synthesize генерирует правильно названные. Они вызываются KVC (и подключаются KVO).

Вот почему -setTimeValue:withTimeScale: сходит с рук [self setMoviePosition:newMoviePosition], который не соответствует вашему -set_moviePosition: метод. Тем не менее, вы должны получить предупреждение (и, во время выполнения, сбой), потому что вы передаете double к сеттеру, который ожидает NSNumber*,

Другие вопросы по тегам