Constrain Int variable to not be 0 in swift

Viewed 33

Is there any provision in Swift to declare an Int variable and constrain it to a min value? E.g. no less than 10? I am aware of Closed and Open Ranges, but I'm not sure how I can convert that to an int. I've also tried using where syntax without luck Thanks in advance.

2 Answers

You can modify it inside didSet

var n : Int = 10 {
    didSet {
        if n < 10{
            print("not ok")
            n = oldValue
        }
    }
}

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"
Related