UXNotificationObs
UXNotificationObs is one registration inside a
UXNotificationCenter. You do not
construct one; addObserver makes it. The centre’s lifetime guarantees are
implemented here.
#use <UXKit> // or #import "UXNotificationCenter.xc"Overview
Section titled “Overview”class UXNotificationObs { weak: Object* observer; // identity, for removeObserver callback method void(UXNotification* note); u8* name; // 0 = match ANY name weak: Object* object; // 0 = match ANY sender}It has four fields, and three of them avoid owning anything.
Why both references are weak
Section titled “Why both references are weak”observer is weak because the centre must not keep a subscriber alive:
window → centre → observer → window would be a retain cycle around every
window in the program.
object, the sender being filtered on, is weak for the same reason: an
observer watching one document should not keep that document in memory.
method is a callback, which never
owns its receiver.
A registration therefore holds nothing alive. When an observer dies its
callback reads false, dispatch skips the entry, and the next sweep prunes it.
For this reason
removeObserver is
hygiene rather than a crash guard.
The two wildcards
Section titled “The two wildcards”Both name and object treat 0 as match anything:
| field | 0 means |
|---|---|
name | every notification, whatever it is called |
object | every sender |
object == 0 is the common case: “tell me about doc.changed from anyone”.
name == 0 is rarer. A registration with no name hears everything, which
suits a logger or a debugging trace. The
addObserver signature
takes a name, so pass 0 explicitly:
nc.addObserver((Object*)tracer, &tracer.onAny, (u8*)0, (Object*)0);Both wildcards at once means “every notification from every sender”. It is cheap to write and expensive to leave in, since it fires on every post in the process.
Names are compared by content
Section titled “Names are compared by content”The centre compares notification names byte by byte, not by pointer. Two copies of the same string match, so a name read from a file, built at run time, or defined in a different compilation unit still works.
With interned pointers instead, "doc.changed" from two places would fail to
match without any error.
Fields
Section titled “Fields”observer
Section titled “observer”weak: Object* observerIdentity only. removeObserver matches on it; the centre never calls it
directly.
method
Section titled “method”callback method void(UXNotification* note)What gets called. It carries its receiver, so the observer field is not used
for dispatch.
u8* name // 0 = anyobject
Section titled “object”weak: Object* object // 0 = any senderSee also
Section titled “See also”UXNotificationCenter: the bus that holds theseUXNotification: what the callback receives- Heap, ARC and weak refs: what
weak:does