我有一个SELECT MAX(StudentID) FROM students GROUP BY CountryID, CityID
变量,我想添加一个约束,例如下面的简化示例:
@State
但是,这看起来不太好(尽管似乎可行),但我真正想做的是以某种方式继承或扩展属性包装器@State private var positiveInt = 0 {
didSet {
if positiveInt < 0 {
positiveInt = 0
}
}
}
,以便可以在此设置器中添加此约束。但是我不知道该怎么做。可能吗
答案 0 :(得分:2)
由于@State
是@State
,因此您不能继承Struct
的子类。您正在尝试操纵模型,因此不应在您的视图中考虑此逻辑。您至少应该以这种方式依赖于您的视图模型:
class ContentViewModel: ObservableObject {
@Published var positiveInt = 0 {
didSet {
if positiveInt < 0 {
positiveInt = 0
}
}
}
}
struct ContentView: View {
@ObservedObject var contentViewModel = ContentViewModel()
var body: some View {
VStack {
Text("\(contentViewModel.positiveInt)")
Button(action: {
self.contentViewModel.positiveInt = -98
}, label: {
Text("TAP ME!")
})
}
}
}
但是,由于SwiftuUI并不是事件驱动的框架(它全都涉及数据,模型,绑定等),我们应该习惯于不对事件做出反应,而应将视图设计为“始终与模型保持一致”。 。在您的示例和上面我的回答中,我们对更改为整数的值做出反应,以覆盖其值并强制重新创建视图。更好的解决方案可能是这样的:
class ContentViewModel: ObservableObject {
@Published var number = 0
}
struct ContentView: View {
@ObservedObject var contentViewModel = ContentViewModel()
private var positiveInt: Int {
contentViewModel.number < 0 ? 0 : contentViewModel.number
}
var body: some View {
VStack {
Text("\(positiveInt)")
Button(action: {
self.contentViewModel.number = -98
}, label: {
Text("TAP ME!")
})
}
}
}
或更简单(因为基本上没有更多的逻辑了):
struct ContentView: View {
@State private var number = 0
private var positiveInt: Int {
number < 0 ? 0 : number
}
var body: some View {
VStack {
Text("\(positiveInt)")
Button(action: {
self.number = -98
}, label: {
Text("TAP ME!")
})
}
}
}
答案 1 :(得分:0)
您不能应用多个propertyWrapper
,但是可以使用2个独立的包装值。首先创建一个将值钳位到Range
的值:
@propertyWrapper
struct Clamping<Value: Comparable> {
var value: Value
let range: ClosedRange<Value>
init(wrappedValue value: Value, _ range: ClosedRange<Value>) {
precondition(range.contains(value))
self.value = value
self.range = range
}
var wrappedValue: Value {
get { value }
set { value = min(max(range.lowerBound, newValue), range.upperBound) }
}
}
接下来,创建一个ObservableObject
作为您的后备商店:
class Model: ObservableObject {
@Published
var positiveValue: Int = 0
@Clamping(0...(.max))
var clampedValue: Int = 0 {
didSet { positiveValue = clampedValue }
}
}
现在您可以在内容视图中使用它:
@ObservedObject var model: Model = .init()
var body: some View {
Text("\(self.model.positiveValue)")
.padding()
.onTapGesture {
self.model.clampedValue += 1
}
}