Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does NumberFormatter's string(from:) return an optional?

Tags:

ios

swift

Documentation link

Why does the NumberFormatter function func string(from number: NSNumber) -> String? return a String? rather than a String? Are there particular inputs or states for a NumberFormatter where this function could return nil? Sometimes I hear these less-than-ideal return types are from Objective-C holdover files, is this one of those cases?

like image 528
Connor Neville Avatar asked Jan 29 '18 15:01

Connor Neville


2 Answers

Just for fun: Here is a (constructed, not real-world) example where string(from:) actually returns nil:

let num = NSNumber(bytes: UnsafeRawPointer(bitPattern: 1)!, objCType: "v")
print(num) // <>

let fmt = NumberFormatter()
fmt.numberStyle = .decimal
let str = fmt.string(from: num)

print(str as Any) // nil

The reason is that this num does not represent a number: It is created using the NSValue (from which its inherits) initializer init(bytes:objCType:) with a value representing void. ("v" is the type encoding for void, the pointer value is irrelevant.)

like image 189
Martin R Avatar answered Oct 23 '22 21:10

Martin R


There's an ancient (2002) response on the Apple mailing list which might partially answer your question:

The strange behavior isn't NSNumber -- NSNumber -stringValue seems to be returning results one would expect. It's NSNumberFormatter which is returning unusual results.

The abstract problem here is that NSNumberFormatter was originally written to handle money amounts for EOF, so it doesn't deal with unusual numbers well (or general purpose string formatting for that matter).

The more concrete problem is that when you ask an NSNumberFormatter for -stringForObjectValue:, if the object is not an NSDecimalNumber, it converts it to an NSDecimalNumber using [NSDecimalNumber decimalNumberWithString:[objectValue stringValue]] which is not going to handle unusual values well, in addition to potentially other issues. A further issue, though I don't know this is the case, is that I don't think there is an NSDecimal (the struct) representation of positive and negative infinity, as there is for NaN.

I don't actually understand that response enough to say that it's why an optional is returned, but I suspect it's related.

There's example code in the original question, but none of it returns a nil, it always gives a string.

like image 40
nevan king Avatar answered Oct 23 '22 20:10

nevan king