SwiftUI 中 Stepper 的奇怪行为
Posted
技术标签:
【中文标题】SwiftUI 中 Stepper 的奇怪行为【英文标题】:Strange Behavior of Stepper in SwiftUI 【发布时间】:2020-03-16 12:28:08 【问题描述】:我想使用 onIncrement 和 onDecrement 在手动(非绑定)模式下使用 Stepper 视图。当我尝试实现下限和上限时,会有一个奇怪的行为,例如。年龄值不低于 1 或高于 10。
如果你尝试下面的代码,你可以在它已经有值“1”之后按两次“-”。它并没有像预期的那样低于 1,但是在另外两次按下“-”按钮后,“-”按钮突然被禁用。如果您然后按“+”,则不会发生任何事情。仅在再按 2 次“+”后,计数器才会按预期做出反应并变为 2。
这是一个错误吗?
struct StepperTest: View
@State private var age = 5
var body: some View
VStack
Stepper("Enter your age", onIncrement:
if self.age < 10
self.age += 1
print("Adding to age")
, onDecrement:
guard self.age > 1 else return
self.age -= 1
print("Subtracting from age")
)
Text("Your age is \(age)")
【问题讨论】:
你为什么不想为此使用绑定? @MojtabaHosseini:因为我想要完全控制 完全控制什么?您已经可以访问editingChange
,并且可以检测到女巫键被触摸。你还需要什么?
主要原因是,我想使用类似 Redux 的架构,其中状态仅由单独模块中的操作更改。使用绑定,可以在各种视图中修改状态。
这就是所谓的单向数据流架构,和这个没有冲突。
【参考方案1】:
递增后检查和重置值似乎可行:
Stepper("Enter your age", onIncrement:
self.age += 1
if self.age > 10 self.age = 10
, onDecrement:
self.age -= 1
if self.age < 1 self.age = 1
)
【讨论】:
【参考方案2】:我认为这里是解释:
/// 如果尝试递增,
onIncrement
将被初始化为nil
///value
将无效。同样,onDecrement
将被初始化 /// 到nil
如果尝试减少value
将无效。
如果你尝试
Stepper("Enter your age", onIncrement:
print("Adding to age")
, onDecrement:
print("Subtracting from age")
)
...您会看到步进器进入了与您描述的相同的状态,因此 Apple 跟踪步进器视图的重建,如果用户对步进器的操作没有启动重建(即无效),它会自行禁用。
另一个问题是为什么不是一次...
【讨论】:
我不完全了解您将如何使用它。我希望有这两个处理程序 onIncrement 和 onDecrement 以及两个属性来启用/禁用加号和减号按钮... 这是 Apple 的一个问题 )),但这是一个记录在案的行为。 我认为这是一个错误。即使我的onIncrement
和onDecrement
中没有任何if/else 逻辑,我也会得到同样的怪异行为。它只是停止并使“+”或“-”变灰。然后,如果您点击另一个进入错误的方向。该评论语法错误且难以理解。【参考方案3】:
我看到了同样的事情。在我看来,这绝对是苹果方面的一个错误。作为提到的评论者之一,您可以使用 onEditingChanged 参数。这应该为您提供所需的所有功能。随着绑定变量随步进器输入而变化,您可以采取行动。它看起来像这样:
Stepper(value: $age, in: 1...10, step: 1, onEditingChanged: didChange in
// take some action or make a calculation
)
Text("Your age is \(age)")
【讨论】:
【参考方案4】:我看到了与在 Xcode 12.5.1 中使用 ios 14.5 描述的类似行为。我发现了这个描述错误的开放雷达:https://openradar.appspot.com/FB7669491
在我的例子中,我在初始化Stepper
时直接将视图模型中的函数作为onIncrement
和onDecrement
参数传递:
Stepper("Label", onIncrement: viewModel.increment, onDecrement: viewModel.decrement)
基于读取雷达,当前问题是由将函数在视图之外作为这些参数的值传递的。将我的代码更改为此解决了我的问题:
Stepper("Label", onIncrement: viewModel.increment , onDecrement: viewModel.decrement )
【讨论】:
以上是关于SwiftUI 中 Stepper 的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章
在 SwiftUI 视图中的 TextField 后面使用多个 SecureField 时的奇怪行为