guard let number as NSString and NSNumber

182 Views Asked by At

I am getting data from different sources, the variable could be a number or a string of number. How do I make sure that "(number as? NSString)" or "(number as? NSNumber)" always success? Something similar to Java optInt, which will never fail even if the number is a String. See example below:

func testNumber()
    {
        var number = 123
        guard let a = (number as? NSNumber)?.intValue else { print("1");return; }
    }

func testNumberString()
{
    var number = "123"
    guard let a = (number as? NSNumber)?.intValue else { print("2");return; } // this failed.
}
func testNumberToString()
{
        var number = 123
        guard let a = (number as? NSString)?.intValue else { print("2");return; } // this sometimes failed too depend on datasource.
}
    
1

There are 1 best solutions below

8
Raja Kishan On

As I understand from your question, you want an integer value at the end, no matter if the input type is string or integer.

You can achieve this by using ExpressibleByStringLiteral.

Here is the demo

extension Int: ExpressibleByStringLiteral {
    public typealias StringLiteralType = String
    
    public init(stringLiteral value: StringLiteralType) {
        self = Int(value) ?? 0
    }
}

This Int extension allows you to accept string value as Int and return int value. If it did not convert it will give you 0 by default.

Example

func testInt() {
    let numberOne: Int = "5656"
    let numberTwo: Int = 1234
    print(numberOne)
    print(numberTwo)
}

Or another way is to create your own ExpressibleByStringLiteral, which helps you to give default value as you want.

struct StringInt: ExpressibleByStringLiteral {
    var value: Int?
    init(stringLiteral value: String) {
        self.value = Int("\(value)")
    }
    
    func wrapped(with defaultValue: Int) -> Int {
        return self.value ?? defaultValue
    }
}

Example

func testInt() {
    var numberThree: StringInt = "5656"
    print(numberThree.value as Any) // with nil or optional value
    
    numberThree = "asf"
    print(numberThree.wrapped(with: 15)) // with default value
    
    /**
     Output
     Optional(5656)
     15
     */
}