Значение привязки на слайдере не обновляется должным образом
Приложение, которым я сейчас работаю, контролирует положение в фильме 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*
,