Допустим, у вас есть пользовательский элемент управления, похожий на NSSlider, но с поддержкой выбора диапазона значений вместо одного значения. Очевидный выбор свойств - minValue, maxValue, leftValue, rightValue или как вы хотите их назвать.
Возможно, вы также захотите убедиться, что leftValue и rightValue всегда лежат между minValue и maxValue. То же самое для minValue и maxValue. Вы не хотите, чтобы они потенциально сделали недействительными существующие leftValue и rightValue, например, установив maxValue на значение ниже текущего rightValue.
Довольно прямолинейно.
Что, однако, вы делаете в случае обеспечения надлежащего доступа / соответствия КВО? Вы просто не можете гарантировать, что KVO устанавливает свойства в правильном порядке (это сначала установка минимального и максимального пределов, а затем других значений).
У меня такой элемент пользовательского интерфейса, и я просто не могу понять, как его запустить, не открывая двери для ложно установленных значений.
Пользовательский элемент управления предназначен для привязки к объекту модели.
Если я сейчас создаю такую модель со значениями (мин: 0,00, макс .: 42,00, левый: 14,00, правый: 28,00) , я получаю следующие настройки в пользовательском элементе управления (мин: 0,00 макс .: 42,00 слева: 1,00 справа: 1,00)
Причина этого в том, что вместо того, чтобы сначала вызывать minValue и maxValue, сначала он вызывает leftValue и rightValue, что приводит к тому, что оба значения заканчиваются на 1.0 (что является maxValue по умолчанию). (После чего maxValue равно , затем устанавливается на правильное значение.)
//[self prepare] gets called by both, [self initWithCoder:] and [self initWithFrame:]
- (void)prepare
{
minValue = 0.0;
maxValue = 1.0;
leftValue = 0.0;
rightValue = 1.0;
}
- (void)setMinValue:(double)aMinValue
{
if (aMinValue < maxValue && aMinValue < leftValue) {
minValue = aMinValue;
[self propagateValue:[NSNumber numberWithDouble:minValue] forBinding:@"minValue"];
[self setNeedsDisplay:YES];
}
}
- (void)setMaxValue:(double)aMaxValue
{
if (aMaxValue > minValue && aMaxValue > rightValue) {
maxValue = aMaxValue;
[self propagateValue:[NSNumber numberWithDouble:maxValue] forBinding:@"maxValue"];
[self setNeedsDisplay:YES];
}
}
- (void)setLeftValue:(double)aLeftValue
{
double newValue = leftValue;
if (aLeftValue < minValue) {
newValue = minValue;
} else if (aLeftValue > rightValue) {
newValue = rightValue;
} else {
newValue = aLeftValue;
}
if (newValue != leftValue) {
leftValue = newValue;
[self propagateValue:[NSNumber numberWithDouble:leftValue] forBinding:@"leftValue"];
[self setNeedsDisplay:YES];
}
}
- (void)setRightValue:(double)aRightValue
{
double newValue = leftValue;
if (aRightValue > maxValue) {
newValue = maxValue;
} else if (aRightValue < leftValue) {
newValue = leftValue;
} else {
newValue = aRightValue;
}
if (newValue != rightValue) {
rightValue = newValue;
[self propagateValue:[NSNumber numberWithDouble:rightValue] forBinding:@"rightValue"];
[self setNeedsDisplay:YES];
}
Это такие времена, когда вы хотите, чтобы Apple открыла источник какао. Или хотя бы некоторые элементы управления для более глубокого осмотра.
Как бы вы внедрили такой элемент управления?
Или более общий: Каков наилучший способ реализации класса, который имеет перекрестно-зависимые свойства при соблюдении KVO?