You could use a property wrapper for this, here is an example with a dynamic limit
@propertyWrapper struct LimitedInt {
let limit: Int
var wrappedValue: Int {
get { internalValue }
set { internalValue = newValue < limit ? limit : newValue }
}
private var internalValue: Int
init(wrappedValue internalValue: Int, limit: Int) {
self.limit = limit
self.internalValue = internalValue < limit ? limit : internalValue
}
}
and it's used when declaring a property like this
@LimitedInt(limit: 10) var first = 12
To make it a little more advanced we could make our property wrapper generic
@propertyWrapper struct Limited<Value: Comparable>
so it could be used with other types than Int. But to make it even more useful we could make it possible to supply the logic for checking the value and correcting it so here is a more versatile version
@propertyWrapper struct Limited<Value> {
var wrappedValue: Value {
get { internalValue }
set { internalValue = validation(newValue) }
}
private var internalValue: Value
private let validation: (Value) -> Value
init(wrappedValue internalValue: Value, validation: @escaping (Value) -> Value ) {
self.internalValue = validation(internalValue)
self.validation = validation
}
}
Our previous example then becomes
@Limited<Int>(validation: { $0 >= 10 ? $0 : 10 }) var first = 12
But we could of course do whatever we want
@Limited<String>(validation: { Calendar.current.isDateInWeekend(.now) ? "Party!!!" : $0.capitalized }) var second = "hello world"