Right place to unobserve notifications in a document

  • Hi,

    for some teaching reasons I have a document class, which observes a
    notification. Of course I have to unobserve this notification, when
    the document is closed. Doing this in -dealloc is no good design
    (fuunctional overhead in -dealloc, garbage collection …).

    But I read in the documentation, that -close (myDocument) wouldn't be
    called in some situations. Is there a save place to unobserve
    notifications? (Or providing other clean-up.) I couldn't find a hint
    in the documentation!?

    Cheers

    Amin Negm-Awad
    <negm-awad...>
  • On Mon, Aug 18, 2008 at 5:59 AM, Negm-Awad Amin <negm-awad...> wrote:
    > Hi,
    >
    > for some teaching reasons I have a document class, which observes a
    > notification. Of course I have to unobserve this notification, when the
    > document is closed. Doing this in -dealloc is no good design (fuunctional
    > overhead in -dealloc, garbage collection …).

    There's nothing wrong with doing it in -dealloc, and in fact this is
    the standard way to do it. Overhead is not a problem. That code has to
    run *sometime*, and -dealloc is not in anybody's critical path the way
    -finalize is. Garbage collection is not a problem, because
    notification observers are held with weak references in a GC
    environment, so you don't need to manually unobserve at all. Also note
    that it's pretty rare and undesirable to write dual-mode code. If
    you're running under GC, just forget about unobserving. If you're not,
    then forget about problems with GC.

    Mike
  • Am Mo,18.08.2008 um 17:37 schrieb Michael Ash:

    > On Mon, Aug 18, 2008 at 5:59 AM, Negm-Awad Amin <negm-awad...>
    >> wrote:
    >> Hi,
    >>
    >> for some teaching reasons I have a document class, which observes a
    >> notification. Of course I have to unobserve this notification, when
    >> the
    >> document is closed. Doing this in -dealloc is no good design
    >> (fuunctional
    >> overhead in -dealloc, garbage collection …).
    >
    > There's nothing wrong with doing it in -dealloc, and in fact this is
    > the standard way to do it. Overhead is not a problem. That code has to
    > run *sometime*, and -dealloc is not in anybody's critical path the way
    > -finalize is. Garbage collection is not a problem, because
    > notification observers are held with weak references in a GC
    Argh, yes, I forgot this.

    > environment, so you don't need to manually unobserve at all. Also note
    > that it's pretty rare and undesirable to write dual-mode code. If
    > you're running under GC, just forget about unobserving. If you're not,
    > then forget about problems with GC.
    Thanks a lot!

    With the fact above, -dealloc seems to be a nice place, because it is
    *not* executed running garbage collection.

    But anyway I do not think, that doing something else then memory
    management in -dealloc is good design. Normally I unregister
    observation in delegate methods like -applicationWillTerminate:.

    >
    >
    > Mike

    Amin Negm-Awad
    <negm-awad...>
  • On Aug 18, 2008, at 11:51 AM, Negm-Awad Amin wrote:
    > But anyway I do not think, that doing something else then memory
    > management in -dealloc is good design. Normally I unregister
    > observation in delegate methods like -applicationWillTerminate:.

    I understand your concern -- you meant "functional overhead" in the
    sense of a design taboo, not a performance cost -- but in this case I
    think -dealloc is not only okay, but sometimes the only correct place
    to unregister a notification.  Suppose an invariant of your design is
    that an object should receive notifications as long as, and only as
    long as, the object exists.  If you unregister too soon, you may have
    an "alive" object that fails to get a notification.  If unregister too
    late, the notification center will send the notification to a dangling
    pointer and your app will crash.

    I think it's okay to unregister in -dealloc because conceptually it's
    related to releasing your ivars.  You're explicitly dissolving a
    relationship between the object being dealloced and some other object
    -- a relationship you have to manually manage in the absence of
    garbage collection.

    --Andy
  • Am Mo,18.08.2008 um 18:18 schrieb Andy Lee:

    > On Aug 18, 2008, at 11:51 AM, Negm-Awad Amin wrote:
    >> But anyway I do not think, that doing something else then memory
    >> management in -dealloc is good design. Normally I unregister
    >> observation in delegate methods like -applicationWillTerminate:.
    >
    > I understand your concern -- you meant "functional overhead" in the
    > sense of a design taboo, not a performance cost
    Oh, yes, sorry for the ambigious statement.

    I'm a fan of Knuths phrase, so I talk about performance very rarely.

    > -- but in this case I think -dealloc is not only okay, but sometimes
    > the only correct place to unregister a notification.  Suppose an
    > invariant of your design is that an object should receive
    > notifications as long as, and only as long as, the object exists.
    > If you unregister too soon, you may have an "alive" object that
    > fails to get a notification.
    This is little bit a circular argumentation: I need it the whole
    lifetime, so i manage it the whole lifetime. Why do you need it until
    the instance becomes deconstructed?

    I think this is the right pattern:
    1. Construct and init the object
    2. Let them work (register observations, handling threads, $whatever … )
    3. Stop them
    4. Deconstruct them

    So there are 4 steps, not 2.

    In former times I often finished functional work in -dealloc. This
    ofen works, no problem. But it is a poor design. Sure, you shouldn't
    develop for garbage collection and reference counting in the same
    code. But thinking about this can sometimes focus a problem with
    design. No design should depend on the memory management model accept
    of the memory managing itself, should it?

    > If unregister too late, the notification center will send the
    > notification to a dangling pointer and your app will crash.
    Of course you have to stop functional work before decnstrcuting the
    instance.

    > I think it's okay to unregister in -dealloc because conceptually
    > it's related to releasing your ivars.  You're explicitly dissolving
    > a relationship between the object being dealloced and some other
    > object -- a relationship you have to manually manage in the absence
    > of garbage collection.
    In this case it seems to be ok. Maybe this is the reason for the weak
    reference.

    Thanks for your thoughts.

    Cheers,
    Amin

    >
    >
    > --Andy
    >
    >

    Amin Negm-Awad
    <negm-awad...>
  • On Mon, Aug 18, 2008 at 11:51 AM, Negm-Awad Amin <negm-awad...> wrote:
    > But anyway I do not think, that doing something else then memory management
    > in -dealloc is good design. Normally I unregister observation in delegate
    > methods like -applicationWillTerminate:.

    I think you may be a little too strict about this.

    First, this really is memory management, it's just not so obvious.
    You're removing another object's weak reference to your own object.
    The logical place to do this is right before your own object is
    deallocated.

    Second, it's fine, even good, to clean up arbitrary resources in
    -dealloc. There are two things to watch out for, though:

    1) You shouldn't clean up *scarce* resources *only* in dealloc. For
    example, file descriptors. It's fine to close fds in dealloc. In fact,
    you really should do this. But you should *also* provide an explicit
    "close" method and use it. The close in dealloc will just function as
    a failsafe. This is because your object's lifetime may be much longer
    than you want it to be due to things like autorelease pools, so you
    want scarce resources to be under explicit control. This is much more
    important in a GC environment than in the manual environment, however.

    2) You shouldn't clean up *external* resources *only* in dealloc. For
    example, if you have an object that keeps a temporary file around,
    then only deleting it in dealloc is a bad idea. This is because, as
    you're probably aware, there's no guarantee that your objects get
    deallocated before your application terminates. But again, it's fine
    to do this kind of cleanup in dealloc as a failsafe, just don't have
    it be the *only* place it happens.

    What you don't want to do is make dealloc part of an RAII (Resources
    Acquisition is Initialization) pattern, or do long running
    computations there, or things like that. But cleaning up external
    references to your object before you disappear is a good thing to do
    there.

    Mike
  • Am Mo,18.08.2008 um 18:57 schrieb Michael Ash:

    > On Mon, Aug 18, 2008 at 11:51 AM, Negm-Awad Amin <negm-awad...>
    >> wrote:
    >> But anyway I do not think, that doing something else then memory
    >> management
    >> in -dealloc is good design. Normally I unregister observation in
    >> delegate
    >> methods like -applicationWillTerminate:.
    >
    > I think you may be a little too strict about this.
    As I said, it is for teching. So Strictness (correct noun?) is a good
    approach.

    > First, this really is memory management, it's just not so obvious.
    > You're removing another object's weak reference to your own object.
    > The logical place to do this is right before your own object is
    > deallocated.
    >
    > Second, it's fine, even good, to clean up arbitrary resources in
    > -dealloc. There are two things to watch out for, though:
    >
    > 1) You shouldn't clean up *scarce* resources *only* in dealloc. For
    > example, file descriptors. It's fine to close fds in dealloc. In fact,
    > you really should do this. But you should *also* provide an explicit
    > "close" method and use it. The close in dealloc will just function as
    > a failsafe. This is because your object's lifetime may be much longer
    > than you want it to be due to things like autorelease pools, so you
    > want scarce resources to be under explicit control. This is much more
    > important in a GC environment than in the manual environment, however.
    Yes, I saw, that observations of notifications can be understood as a
    kind of memory management. But you can generalize this argumentation –
    and then it becomes definetly wrong.

    In this sense KVO is "a kind of memory management", too. Today I would
    never deregister a KVO-observer in -dealloc as I did it some years ago.

    > 2) You shouldn't clean up *external* resources *only* in dealloc. For
    > example, if you have an object that keeps a temporary file around,
    > then only deleting it in dealloc is a bad idea. This is because, as
    > you're probably aware, there's no guarantee that your objects get
    > deallocated before your application terminates. But again, it's fine
    > to do this kind of cleanup in dealloc as a failsafe, just don't have
    > it be the *only* place it happens.
    >
    > What you don't want to do is make dealloc part of an RAII (Resources
    > Acquisition is Initialization) pattern,
    Yes, that's it. In the past I handled – internal! – ressources very
    often this way. I stopped doing so. GC was just the initial thinking:
    "Hey, you are doing something in a method for memory managemt, which
    has no relation to memory management."

    As I said, I never have had problems with this approach in woking
    code. But I do not like it anymore for design reasons.

    > or do long running
    > computations there,
    No, there is no performance issue in my mind. It's simply design.

    > or things like that. But cleaning up external
    > references to your object before you disappear is a good thing to do
    > there.
    I'll continue thinking about this …

    Cheers,
    Amin

    >
    >
    > Mike

    Amin Negm-Awad
    <negm-awad...>
  • On Aug 18, 2008, at 12:49 PM, Negm-Awad Amin wrote:
    > Am Mo,18.08.2008 um 18:18 schrieb Andy Lee:
    >> -- but in this case I think -dealloc is not only okay, but
    >> sometimes the only correct place to unregister a notification.
    >> Suppose an invariant of your design is that an object should
    >> receive notifications as long as, and only as long as, the object
    >> exists.  If you unregister too soon, you may have an "alive" object
    >> that fails to get a notification.
    > This is little bit a circular argumentation: I need it the whole
    > lifetime, so i manage it the whole lifetime. Why do you need it
    > until the instance becomes deconstructed?

    It's only circular in that I specifically selected a class of
    situations where it makes the most sense. :)

    > I think this is the right pattern:
    > 1. Construct and init the object
    > 2. Let them work (register observations, handling threads, $whatever
    > … )
    > 3. Stop them
    > 4. Deconstruct them
    >
    > So there are 4 steps, not 2.

    This pattern is fine and necessary in many cases, but there are also
    plenty of cases where it is not viable. For example, it may not be
    clear when the object can "stop" listening for notifications.  It may
    literally be when all other objects are done with it, i.e., when its
    retain count goes to zero, and in a dynamic system you may have no way
    of knowing which will be the last object to release your object.

    IMO imposing a start-stop paradigm on every class that wants to
    register interest in notifications -- and engineering every class so
    that your object can't possibly be released until it is "stopped" --
    is just as much a design error as putting functional work in -
    dealloc.  I would encourage you to reconsider.

    In the cases where you do have a start-stop paradigm, you should put a
    "stop" in -dealloc anyway, as Michael argued.

    >> I think it's okay to unregister in -dealloc because conceptually
    >> it's related to releasing your ivars.  You're explicitly dissolving
    >> a relationship between the object being dealloced and some other
    >> object -- a relationship you have to manually manage in the absence
    >> of garbage collection.
    > In this case it seems to be ok. Maybe this is the reason for the
    > weak reference.

    The weak reference is to avoid retain cycles (the same reason why
    delegates are not retained).  With GC turned on, retain cycles are not
    a problem so you don't have to worry about weak references to self,
    just as you don't have to bother releasing strong references to
    ivars.  In the absence of GC, you have to break connections manually,
    and that's all this is.  In fact, you should also break delegate
    connections to self in the same place, for the same reason.  (Hm, I'm
    not sure whether I'm doing this in my own code -- I'd better check.)

    You mentioned KVO in another reply.  I haven't used KVO, so I'd be
    interested if anyone has a response to your counterexample.

    --Andy
  • Am Mo,18.08.2008 um 20:14 schrieb Andy Lee:

    > On Aug 18, 2008, at 12:49 PM, Negm-Awad Amin wrote:
    >> Am Mo,18.08.2008 um 18:18 schrieb Andy Lee:
    >>> -- but in this case I think -dealloc is not only okay, but
    >>> sometimes the only correct place to unregister a notification.
    >>> Suppose an invariant of your design is that an object should
    >>> receive notifications as long as, and only as long as, the object
    >>> exists.  If you unregister too soon, you may have an "alive"
    >>> object that fails to get a notification.
    >> This is little bit a circular argumentation: I need it the whole
    >> lifetime, so i manage it the whole lifetime. Why do you need it
    >> until the instance becomes deconstructed?
    >
    > It's only circular in that I specifically selected a class of
    > situations where it makes the most sense. :)
    >
    >> I think this is the right pattern:
    >> 1. Construct and init the object
    >> 2. Let them work (register observations, handling threads,
    >> $whatever … )
    >> 3. Stop them
    >> 4. Deconstruct them
    >>
    >> So there are 4 steps, not 2.
    >
    > This pattern is fine and necessary in many cases, but there are also
    > plenty of cases where it is not viable. For example, it may not be
    > clear when the object can "stop" listening for notifications.  It
    > may literally be when all other objects are done with it, i.e., when
    > its retain count goes to zero, and in a dynamic system you may have
    > no way of knowing which will be the last object to release your
    > object.
    >
    > IMO imposing a start-stop paradigm on every class that wants to
    > register interest in notifications -- and engineering every class so
    > that your object can't possibly be released until it is "stopped" --
    > is just as much a design error as putting functional work in -
    > dealloc.  I would encourage you to reconsider.
    As I said, in the past I used this pattern very often. And indeed the
    reason was, that if somebody A is retaining somebody B, A uses B. So I
    can mix up functional work and memory management. This seems to be
    convient.

    If you put it together, you have no possibility of stopping somebody
    without releasing it. And since you can not be sure, that somebody
    else holds it, you have to reinstantiate B for a new start. I think in
    practice a "2-step-pattern" makes sharing of the functionality harder!

    > In the cases where you do have a start-stop paradigm, you should put
    > a "stop" in -dealloc anyway, as Michael argued.
    You should throw an exception or at least log something, as oberserved
    objects actually do ("dealloc while observation in place" or something
    like this).
    >
    >
    >>> I think it's okay to unregister in -dealloc because conceptually
    >>> it's related to releasing your ivars.  You're explicitly
    >>> dissolving a relationship between the object being dealloced and
    >>> some other object -- a relationship you have to manually manage in
    >>> the absence of garbage collection.
    >> In this case it seems to be ok. Maybe this is the reason for the
    >> weak reference.
    > The weak reference is to avoid retain cycles (the same reason why
    > delegates are not retained).
    We talked about GC. The need for a weak reference using RC is quite
    clear.

    > With GC turned on, retain cycles are not a problem so you don't have
    > to worry about weak references to self, just as you don't have to
    > bother releasing strong references to ivars.
    Since the observed object (maybe notification center) will still hold
    a reference to the observing object, there is a problem. The
    *observer* will not be freed, if the observed is still living.
    Obviously you have a problem using GC,  for example if you have an
    observing window and an observed model instance. The model probably
    lives longer than the window. (Think of info windows …)

    This seems to be the reason for the weak reference using GC.

    > In the absence of GC, you have to break connections manually, and
    > that's all this is.  In fact, you should also break delegate
    > connections to self in the same place, for the same reason.  (Hm,
    > I'm not sure whether I'm doing this in my own code -- I'd better
    > check.)
    >
    > You mentioned KVO in another reply.  I haven't used KVO, so I'd be
    > interested if anyone has a response to your counterexample.

    Still waiting … ;--)

    Cheers,
    Amin

    >
    >
    > --Andy
    >
    >

    Amin Negm-Awad
    <negm-awad...>
  • >
    > Am Mo,18.08.2008 um 20:14 schrieb Andy Lee:
    >>
    >
    > Since the observed object (maybe notification center) will still
    > hold a reference to the observing object, there is a problem. The
    > *observer* will not be freed, if the observed is still living.
    > Obviously you have a problem using GC,  for example if you have an
    > observing window and an observed model instance. The model probably
    > lives longer than the window. (Think of info windows …)
    >
    > This seems to be the reason for the weak reference using GC.

    I've been reading this thread and I don't understand it in the case of
    GC. Why don't you still have to remove the observer from the
    notification center when you are not longer using it. Even if it is
    held as a weak reference, it will still remain registered for
    receiving notifications, so what when the observer is eventually
    collected, won't the notification center continue sending messages to
    the observer as long as it remains registered to receive them?, Please
    clarify.

    Joan Lluch
  • Am Mi,20.08.2008 um 15:37 schrieb Joan Lluch (casa):

    >
    >>
    >> Am Mo,18.08.2008 um 20:14 schrieb Andy Lee:
    >>>
    >>
    >> Since the observed object (maybe notification center) will still
    >> hold a reference to the observing object, there is a problem. The
    >> *observer* will not be freed, if the observed is still living.
    >> Obviously you have a problem using GC,  for example if you have an
    >> observing window and an observed model instance. The model probably
    >> lives longer than the window. (Think of info windows …)
    >>
    >> This seems to be the reason for the weak reference using GC.
    >
    > I've been reading this thread and I don't understand it in the case
    > of GC. Why don't you still have to remove the observer from the
    > notification center when you are not longer using it. Even if it is
    > held as a weak reference, it will still remain registered for
    > receiving notifications, so what when the observer is eventually
    > collected, won't the notification center continue sending messages
    > to the observer as long as it remains registered to receive them?,
    > Please clarify.
    First I want to say, that I'm happy to have a thread on this list,
    which is not related to a concrete problem, but discusses a design. I
    like that. :-)

    Second: As you read, *I* would prefer to unregister the observer
    explicitly. You can do this in -finalize, but I do not have to repeat
    the design problems with finalization. *I* wanted a delegate method or
    a defined method to be overwritten in a subclass (I mentioned -close)
    to do it explicitly, *before* destroying the object. You ask the wrong
    person …

    Third, to your question: Weak references in GC – they have nothing to
    do with "retainless" weak references using RC – are nullified
    automatically. If you use GC the weak collection should be modified
    appropiate by the collector itself. So this might be no problem. (I
    didn't test it, because it is not my idea.)

    Anyway, as said: *I do not* want to handle the unregister this way. I
    want to handle it explicitly, but found no -willClose method or
    something like this. (You cannot relay on -close, as I said in the OP.)

    Cheers,
    Amin

    >
    >
    > Joan Lluch
    >
    >

    Amin Negm-Awad
    <negm-awad...>
  • Joan Lluch

    El 20/08/2008, a las 16:05, Negm-Awad Amin escribió:

    >
    > Am Mi,20.08.2008 um 15:37 schrieb Joan Lluch (casa):
    >>>
    >>
    >> I've been reading this thread and I don't understand it in the case
    >> of GC. Why don't you still have to remove the observer from the
    >> notification center when you are not longer using it. Even if it is
    >> held as a weak reference, it will still remain registered for
    >> receiving notifications, so what when the observer is eventually
    >> collected, won't the notification center continue sending messages
    >> to the observer as long as it remains registered to receive them?,
    >> Please clarify.
    > First I want to say, that I'm happy to have a thread on this list,
    > which is not related to a concrete problem, but discusses a design.
    > I like that. :-)
    >
    > Second: As you read, *I* would prefer to unregister the observer
    > explicitly. You can do this in -finalize, but I do not have to
    > repeat the design problems with finalization. *I* wanted a delegate
    > method or a defined method to be overwritten in a subclass (I
    > mentioned -close) to do it explicitly, *before* destroying the
    > object. You ask the wrong person …
    >
    > Third, to your question: Weak references in GC – they have nothing
    > to do with "retainless" weak references using RC – are nullified
    > automatically. If you use GC the weak collection should be modified
    > appropiate by the collector itself. So this might be no problem. (I
    > didn't test it, because it is not my idea.)
    >
    I understand what is your preferred approach, which it is also what I
    would do. I can add to it that I even thought that you *have to*
    *always* unregister the observers when you have done with them. This
    is obviously true in RC environment, but this is apparently not true
    in the case of GC. This is the part I don't get. I would appreciate if
    someone would clarify it for me.

    Joan Lluch
  • Am Mi,20.08.2008 um 16:58 schrieb Joan Lluch (casa):

    >
    > Joan Lluch
    >
    > El 20/08/2008, a las 16:05, Negm-Awad Amin escribió:
    >
    >>
    >> Am Mi,20.08.2008 um 15:37 schrieb Joan Lluch (casa):
    >>>>
    >>>
    >>> I've been reading this thread and I don't understand it in the
    >>> case of GC. Why don't you still have to remove the observer from
    >>> the notification center when you are not longer using it. Even if
    >>> it is held as a weak reference, it will still remain registered
    >>> for receiving notifications, so what when the observer is
    >>> eventually collected, won't the notification center continue
    >>> sending messages to the observer as long as it remains registered
    >>> to receive them?, Please clarify.
    >> First I want to say, that I'm happy to have a thread on this list,
    >> which is not related to a concrete problem, but discusses a design.
    >> I like that. :-)
    >>
    >> Second: As you read, *I* would prefer to unregister the observer
    >> explicitly. You can do this in -finalize, but I do not have to
    >> repeat the design problems with finalization. *I* wanted a delegate
    >> method or a defined method to be overwritten in a subclass (I
    >> mentioned -close) to do it explicitly, *before* destroying the
    >> object. You ask the wrong person …
    >>
    >> Third, to your question: Weak references in GC – they have nothing
    >> to do with "retainless" weak references using RC – are nullified
    >> automatically. If you use GC the weak collection should be modified
    >> appropiate by the collector itself. So this might be no problem. (I
    >> didn't test it, because it is not my idea.)
    >>
    > I understand what is your preferred approach, which it is also what
    > I would do. I can add to it that I even thought that you *have to*
    > *always* unregister the observers when you have done with them. This
    > is obviously true in RC environment, but this is apparently not true
    > in the case of GC. This is the part I don't get. I would appreciate
    > if someone would clarify it for me.
    Apple can clarify. Of course I do not know, which collection they use,
    but as a prototype:
    http://developer.apple.com/documentation/Cocoa/Reference/NSMapTable_class/R
    eference/NSMapTable.html

    It can hold weak references to its keys and/or values.
    Keys and/or values held "weakly" in a manner that entries are removed
    when one of the objects is collected under garbage collection.

    If you are not using garbage collection, you must explicitly remove
    entries as you would from a dictionary. In addition to being held
    weakly, keys or values may be copied on input or may use pointer
    identity for equality and hashing.

    >
    As I said: Weak collections are modified automatically, if a member is
    collected.
    If the notification center handles the notification observers in a
    collection (probably they will do), the observer is automatically
    removed when collected.

    Cheers,
    Amin

    >
    > Joan Lluch
    >
    >

    Amin Negm-Awad
    <negm-awad...>
  • On Wed, Aug 20, 2008 at 9:37 AM, Joan Lluch (casa) <carbonat...> wrote:
    >
    >>
    >> Am Mo,18.08.2008 um 20:14 schrieb Andy Lee:
    >>>
    >>
    >> Since the observed object (maybe notification center) will still hold a
    >> reference to the observing object, there is a problem. The *observer* will
    >> not be freed, if the observed is still living. Obviously you have a problem
    >> using GC,  for example if you have an observing window and an observed model
    >> instance. The model probably lives longer than the window. (Think of info
    >> windows …)
    >>
    >> This seems to be the reason for the weak reference using GC.
    >
    > I've been reading this thread and I don't understand it in the case of GC.
    > Why don't you still have to remove the observer from the notification center
    > when you are not longer using it. Even if it is held as a weak reference, it
    > will still remain registered for receiving notifications, so what when the
    > observer is eventually collected, won't the notification center continue
    > sending messages to the observer as long as it remains registered to receive
    > them?, Please clarify.

    "Weak reference" is a bit of an abbreviation in this case. What
    NSNotificationCenter uses (and what you should always use if you want
    a weak reference in GC land) is a *zeroing* weak reference.

    To illustrate, here is how you create a zeroing weak reference:

    __weak id someRef;

    Now you can use this just like any other variable:

    someRef = myObj;

    The trick is that when the object that it points to goes away, someRef
    gets zeroed out:

    id localObj = someRef;
    if(!localObj) // the object was destroyed!

    The NSPointerArray, NSHashTable, and NSMapTable classes allow you to
    use zeroing weak references as part of a collection. For example,
    NSNotificationCenter could use an NSMapTable with weak objects, and
    then any time an object in the table gets destroyed, its entry
    disappears and NSNotificationCenter will no longer message it.

    Mike
  • On Aug 20, 2008, at 07:58, Joan Lluch (casa) wrote:

    > I understand what is your preferred approach, which it is also what
    > I would do. I can add to it that I even thought that you *have to*
    > *always* unregister the observers when you have done with them. This
    > is obviously true in RC environment, but this is apparently not true
    > in the case of GC. This is the part I don't get. I would appreciate
    > if someone would clarify it for me.

    This thread has wandered off into confusion because it mixes up 2
    unrelated kinds of "observer". These two mechanisms have absolutely
    nothing in common, except the word "observe".

    Under GC, notification centers keep weak references to their
    notification observers. As Michael pointed out, these references are
    automatically zeroed when the observer goes away, so the notification
    center can detect the situation and clean itself up accordingly. This
    does *not* mean that an observer can't be removed until it goes
    through its finalize -- removeObserver: can of course be called at any
    time.

    In a non-GC app, you always have to call removeObserver:, and the
    observer's dealloc is a reasonable place to ensure that it's been done
    before the observer goes away. Under GC, there's no equivalent of
    dealloc, but happily there's no need to ensure that it's been done.

    Under GC, KVO keeps a strong reference to the KVO observer in (or,
    rather, in a private constructed-on-the-fly sort-of-subclass of) the
    observed object. If the observer goes away, the strong reference is
    left dangling and will usually result in an exception. With luck,
    Apple will decide to change the KVO implementation sometime to keep
    weak references, so that such dangling references won't exist. If it
    makes the change, that also does not mean that an observer can't be
    removed except by being finalized -- removeObserver:forKeyPath: can of
    course be called at any time.

    In a non-GC app, again, dealloc is a reasonable place to ensure that
    removeObserver:forKeyPath: has been called. Under GC (until Apple
    decides to change KVO), there's no way to *ensure* that the
    observation has been "cancelled" before the observer goes away. You
    have to rely on someone calling it earlier, and it's sometimes a
    significant programming headache to make sure this gets done properly.
previous month august 2008 next month
MTWTFSS
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Go to today