swiftPunk
swiftPunk

Reputation: 1

How can I use same logic for a Type in optional/non-optional case

I have a closure that adds zero to left part of a number in a condition and return String. The number type is Int but it must work if the Type is optional Int.

I ended up to repeat my code, my goal is stop repeating my code in the way that my code works for Int and Int?

extension Int {
    var addLeftZero: String { addLeftZeroClosure(self) }
}


extension Optional where Wrapped == Int {
    var addLeftZero: String {

        if let unwrappedValue: Wrapped = self { return addLeftZeroClosure(unwrappedValue) }
        else { return "00" }
        
    }
}



let addLeftZeroClosure: (Int) -> String = { value in

    if (value >= 10) { return String(describing: value) }
    else { return "0" + String(describing: value) }
    
}

Upvotes: 0

Views: 59

Answers (1)

George
George

Reputation: 30431

Read both parts first, before picking solution to use.


You could do something like this:

extension Int {
    var addLeftZero: String {
        String(format: "%02d", self)
    }
}

extension Optional where Wrapped == Int {
    var addLeftZero: String {
        self?.addLeftZero ?? "00"
    }
}

Example usage:

let a: Int = 1
let b: Int? = 2
let c: Int? = nil

print(a.addLeftZero) // Prints: 01
print(b.addLeftZero) // Prints: 02
print(c.addLeftZero) // Prints: 00

Although Xcode code-completion will automatically do a?.addLeftZero instead of a.addLeftZero.


A (possibly) better way would be to have this abstracted away in your own custom type:

struct PaddedNumber: ExpressibleByIntegerLiteral, ExpressibleByNilLiteral {
    let value: Int?

    var string: String {
        if let value = value {
            return String(format: "%02d", value)
        } else {
            return "00"
        }
    }

    init(_ value: Int?) {
        self.value = value
    }

    init(integerLiteral value: IntegerLiteralType) {
        self.value = value
    }

    init(nilLiteral: ()) {
        value = nil
    }
}

Example usage:

let a: PaddedNumber = 1
let b: PaddedNumber = 2
let c: PaddedNumber = nil

print(a.string) // Prints: 01
print(b.string) // Prints: 02
print(c.string) // Prints: 00

Upvotes: 1

Related Questions