Swift Scalars - Return nil instead of default values?

Question

Why was the Swift SDK designed such that if I do this:

someDictionaryObject.int(forKey: "foo")

And foo does not exist or is not numeric, 0 is returned instead of a nil? This makes it impossible to distinguish between:

“I actually stored 0 for this property” and “This property was either missing or something entirely incorrect, such as a String, that I should handle.”

Context

I can solve the “does foo exist at all?” problem for DictionaryObject by using contains(key: "foo") But for ArrayObject where I’m iterating indices, I no longer have any way of distinguishing between “the property was actually 0” and every other case that automatically becomes zero.

It’s as if we took Date and, if the object that was supposed to be a Date is invalid, we just returned a Date set to 1 January 1970. Now we’d be unable to answer the question: “Is that the real date, or is it the error marker?”

API Improvement

I realize this behavior is now baked in, so it can’t be changed. But could we get an improved, alternate API alongside it? Something where if I ask for a scalar Int, Bool, Double, etc and the thing in the database is NOT, in fact, that kind of value, I get back nil so I can react appropriately?

Hi @bdkjones,

Currently, there is no optional return for scalars. The underlying implementation is using Foundation framework i.e integerValue, which defaults to 0 if NaN or nil.

I will file a ticket for this as an improvement to the current Swift API (will update when I have it).

Meanwhile, a solution to this would be using value(forKey:) API. DictionaryObject Class Reference

The typed accessors are, ultimately, conveniences.

If you expect different possible types in an array, use the general-purpose valueAt, which returns Any?. Then do your own checking for nil or for the different types.

Are the number types returned from value(at:) scalars or NSNumber? I’m trying to avoid the overhead of NSNumber if possible.

Scalars. We have a pretty optimized internal data format called Fleece, and convert from that to platform values.

(But note that NSNumber often has less overhead than you expect; a lot of integers are stored as tagged pointers with no heap allocation.)

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.