gpt4 book ai didi

cocoa - 如何确保类似 NSSlider 的自定义控件的 KVO 行为正确?

转载 作者:行者123 更新时间:2023-12-03 18:04:53 24 4
gpt4 key购买 nike

假设您有一个类似于 NSSlider 的自定义控件,但支持选择一系列值,而不是单个值。属性的明显选择是 minValue、maxValue、leftValue、rightValue,或者您想要的任何名称。
您可能还想确保 leftValue 和 rightValue 始终位于 minValue 和 maxValue 之间。 minValue 和 maxValue 相同。您不希望它们潜在地使现有的 leftValue 和 rightValue 无效,例如将 maxValue 设置为低于当前 rightValue 的值。

到目前为止非常简单。

但是,为了确保正确的 KVO 可访问性/合规性,您会做什么?您根本无法确保 KVO 按正确的顺序设置属性(首先设置最小和最大限制,然后设置其他值)。

我碰巧有这样一个 UI 元素,并且根本无法弄清楚如何在不打开错误设置值的大门的情况下运行它。

自定义控件旨在绑定(bind)到模型对象。如果我现在使用值 (min: 0.00 max: 42.00 left: 14.00 right: 28.00) 创建这样的模型,我最终会在自定义控件中进行以下设置 (min: 0.00 max :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];
}

正是在这样的时刻,您希望苹果开放 cocoa 的来源。或者至少是一些用于更深入检查的控制。

您将如何实现这样的控制?

或者更一般地说:在遵守 KVO 的同时实现具有交叉依赖属性的类的最佳实践是什么?

最佳答案

哇。这是一个棘手的问题。正如您已经发现的,您无法确保 KVO 消息按任何特定顺序发送。

这是一个想法:在你的 setLeftValue: 中和setRightValue:访问器,而不是修剪值,为什么不直接存储传入的值,然后在访问时修剪该值。

例如:

- (void)setLeftValue:(double)value {
leftValue = value;
[self propagateValue:[NSNumber numberWithDouble:self.leftValue] forBinding:@"leftValue"]; // Note the use of the accessor here
[self setNeedsDisplay:YES];
}

- (double)leftValue {
return MAX(self.minValue, MIN(self.maxValue, leftValue));
}

这样,一次minValuemaxValue已设置,leftValuerightValue将代表正确的值。并且,通过使用自定义访问器,您可以确保您的约束 minValue <= leftValue/rightValue <= maxValue已保留。

此外,对于您正在编写的代码,MINMAX预处理器宏将为您节省大量精力。

关于cocoa - 如何确保类似 NSSlider 的自定义控件的 KVO 行为正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3149890/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com