UXNull
UXNull is a single shared object meaning “there is explicitly nothing
here”, which differs from “there is nothing here”. It is shaped like
NSNull.
#use <UXKit> // or #import "UXNull.xc"Overview
Section titled “Overview”A collection stores Object*, and 0 is a valid nil. A sentinel is still
needed because absent and present but empty are different facts, and some
data must express the second:
- a JSON document containing
"middleName": null, where the key is there - a sparse row whose third column was cleared on purpose
- a cache entry recording “looked, and found nothing” so the lookup is not repeated
Stored as 0, these become indistinguishable from “no such key”, “never
set” and “not cached yet”. UXNull.null() is an object you can put in
a collection, and it stands for the first of each pair.
Array<Object>* row = new Array();row.add(name); // a valuerow.add(UXNull.null()); // explicitly empty// a third column simply never added — absentTopics
Section titled “Topics”static UXNull* null(void)The one shared instance, made on first use. Every call returns the same object, so identity comparison is the test. Nothing is allocated per use and nothing needs freeing.
isNull
Section titled “isNull”static bool isNull(Object* o)Whether this reference is the sentinel. False for a real nil.
UXNull.isNull(UXNull.null()) // trueUXNull.isNull((Object*)0) // false — nil is absent, not explicitly emptyUse this when the distinction matters, for example a JSON writer that emits
null for the sentinel and omits the key when the value is absent.
isNothing
Section titled “isNothing”static bool isNothing(Object* o)Nil or the sentinel: “there is no value here, however it was expressed”.
UXNull.isNothing((Object*)0) // trueUXNull.isNothing(UXNull.null()) // trueUXNull.isNothing(name) // falseUse this when you are about to use a value and only need to know there is
none. Most call sites want isNothing; isNull is for the ones that must
preserve the difference on the way back out.
The singleton pattern
Section titled “The singleton pattern”This class is also the toolkit’s reference example of a lazily-made shared instance:
UXNull* gUXNull; // file-scope global
static UXNull* null(void) { if (gUXNull == (UXNull*)0) { gUXNull = new UXNull(); } return gUXNull;}Nothing is allocated until something asks; after that every caller gets the same
object. UXNotificationCenter.shared
and UXLog.shared have the same shape.
The instance is immutable and carries no state, so sharing it across a whole program costs one allocation and raises no ownership question.
Example
Section titled “Example”Round-tripping a row where “cleared” must stay distinct from “missing”:
Array<Object>* row = new Array();row.add(title);row.add(UXNull.null()); // the user cleared this cell
for (u16 i = 0; i < row.count(); i = i + 1) { Object* v = row.get(i); if (UXNull.isNull(v)) { Stdio.printf("col %d: cleared\n", i); } else if (v == (Object*)0) { Stdio.printf("col %d: absent\n", i); } else { Stdio.printf("col %d: a value\n", i); }}If the cleared cell were stored as 0, the writer could not tell it from a
column that was never filled in, and the round trip would drop the user’s
edit.
Conforms to
Section titled “Conforms to”- Inherits
Object
See also
Section titled “See also”UXJSON: where a literalnullin a document becomes this sentinelUXCache: a negative result is a value, not an absenceUXNotificationCenter: the same singleton shape