Format Int64 with thousand separators

You mean when you call numberFormatter.stringFromNumber(12345678) after the above code, like this?

let i64: Int64 = 1234567890
numberFormatter.stringFromNumber(i64)

Doesn’t look like Swift will cast from an Int64 to an NSNumber:

let i = 1234567890
let n = i as NSNumber  // OK
numberFormatter.stringFromNumber(i)  // Also OK

// Compiler error: 'Int64' is not convertible to 'NSNumber'
let n64 = i64 as NSNumber
// so the implicit conversion will also fail:
numberFormatter.stringFromNumber(i64)

This is a bit confounding, since Swift Ints are themselves usually the same size as Int64s.

You can work around it by constructing an NSNumber by hand:

let n64 = NSNumber(longLong: i64)

BTW beware that var trick: it’s nice that it encapsulates all the relevant code for creating numberFormatter, but that code will run afresh every time you use it. As an alternative you could do this:

let numberFormatter: NSNumberFormatter = {
    let formattedNumber = NSNumberFormatter()
    formattedNumber.numberStyle = .DecimalStyle
    formattedNumber.maximumFractionDigits = 0
    return formattedNumber
}()

If it’s a property in a struct/class, you could also make it a lazy var which has the added benefit of only being running if the variable is used, like your var, but only once.

struct Thing {
    lazy var numberFormatter: NSNumberFormatter = {
        println("blah")
        let formattedNumber = NSNumberFormatter()
        formattedNumber.numberStyle = .DecimalStyle
        formattedNumber.maximumFractionDigits = 0
        return formattedNumber
    }()
}

extension Formatter {
    static let decimalNumber: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        return formatter
    }()
}

extension Numeric {
    var formatted: String { Formatter.decimalNumber.string(for: self) ?? "" }
}

let x: Int64 = 1000000
x.formatted   // "1,000,000"

Tags:

Ios

Xcode

Swift