I do something like this:
import Foundation
enum Formatters {
static private var numberFormatter: NumberFormatter = {
let nf = NumberFormatter()
nf.numberStyle = .decimal
return nf
}()
static private var percentageFormatter: NumberFormatter {
let nf = NumberFormatter()
nf.numberStyle = .percent
nf.minimumFractionDigits = 1
nf.minimumFractionDigits = 1
return nf
}
static private var memoryColumnFormatter: ByteCountFormatter = {
let bcf = ByteCountFormatter()
bcf.countStyle = .memory
bcf.allowsNonnumericFormatting = false
bcf.formattingContext = .listItem
return bcf
}()
// Mark: Convenience overloads
// I really wish NSNumebr had an initializer that took a generic BinaryInteger
static func format(number: Int32) -> String {
return self.format(number: NSNumber(value: number))
}
static func format(number: UInt32) -> String {
return self.format(number: NSNumber(value: number))
}
static func format(pointer: UInt64) -> String {
"0x" + String(pointer, radix: 16, uppercase: true, width: 16)
}
static func format(percentage: Double) -> String {
return percentageFormatter.string(from: NSNumber(value: percentage))!
}
static func format(byteCountForMemoryColumn byteCount: UInt64) -> String {
return memoryColumnFormatter.string(fromByteCount: Int64(byteCount))
}
static func format(number: NSNumber) -> String {
return numberFormatter.string(from:number)!
}
}