In dealloc(): ref @property, Can I use "<property object> = nil; " vs "[<property object> release]; " ?

  • Assuming the following:



    @property(retain) myVar;

    ...

    @synthesize myVar;



    ...



    -(void) dealloc {

      // Can I use:

      self.myVar = nil;

    // versus:

    [myVar release];  //  ?

    }





    I've seen examples of using [myVar release].  But doesn't setting myVar
    = nil does the same thing?



    Which is the preferred way?



    Ric.
  • On Oct 8, 2008, at 8:49 AM, Lee, Frederick wrote:

    > I've seen examples of using [myVar release].  But doesn't setting
    > myVar
    > = nil does the same thing?
    >
    >
    >
    > Which is the preferred way?

    This is a point of more contention than you may realize. The former
    is, of course, equivalent to

    [self setMyVar:nil];

    which, as it calls a method on self during [self dealloc], is
    something frowned upon by many. It also triggers the KVO process,
    though if you're in dealloc, any KVO concerns should have finished
    long ago. On the other hand, it's a "purer" OO call style and allows
    you to stick with the property syntax as much as possible and lets you
    worry a bit less about memory management, which is nice.

    YMMV, but you're probably safer doing [myVar release];. If you ever
    end up implementing your own -setMyVar: and it has side effects, there
    be demons ahead.

    -> jp
  • On Oct 8, 2008, at 8:49 AM, Lee, Frederick wrote:

    > Assuming the following:
    >
    >
    >
    > @property(retain) myVar;
    >
    > ...
    >
    > @synthesize myVar;
    >
    >
    >
    > ...
    >
    >
    >
    > -(void) dealloc {
    >
    > // Can I use:
    >
    > self.myVar = nil;
    >
    > // versus:
    >
    > [myVar release];  //  ?
    >
    > }
    >
    >
    >
    >
    >
    > I've seen examples of using [myVar release].  But doesn't setting
    > myVar
    > = nil does the same thing?
    >
    >
    >
    > Which is the preferred way?
    >

    I prefer doing [myVar release]. Mainly because I don't want setMyVar
    getting called during dealloc. And by this time there *shouldn't* be
    any KVO observers for myVar (assuming the property was observed at all
    before).

    Yea yea – you've done @synthesize here so we know that the setter
    doesn't do any custom work. But since we're in dealloc, we are –
    obviously – not running under GC. Under refcounting, if you didn't
    declare your property nonatomic, you're gonna take a lock during
    dealloc to do setMyVar:nil.

    --------------------------
    RONZILLA
  • I've been setting my property thusly:



    @property (nonatomic, retain) myVar;



    ...what about:



    @property (nonatomic, copy) myVar; ?



    Ric.



    From: Ron Lue-Sang [mailto:<luesang...>]
    Sent: Wednesday, October 08, 2008 11:06 AM
    To: Lee, Frederick
    Cc: <cocoa-dev...>
    Subject: Re: In dealloc(): ref @property, Can I use "<property object> =
    nil; " vs "[<property object> release]; " ?





    On Oct 8, 2008, at 8:49 AM, Lee, Frederick wrote:

    Assuming the following:

    @property(retain) myVar;

    ...

    @synthesize myVar;

    ...

    -(void) dealloc {

      // Can I use:

    self.myVar = nil;

    // versus:

    [myVar release];  //  ?

    }

    I've seen examples of using [myVar release].  But doesn't setting myVar
    = nil does the same thing?

    Which is the preferred way?



    I prefer doing [myVar release]. Mainly because I don't want setMyVar
    getting called during dealloc. And by this time there *shouldn't* be any
    KVO observers for myVar (assuming the property was observed at all
    before).



    Yea yea - you've done @synthesize here so we know that the setter
    doesn't do any custom work. But since we're in dealloc, we are -
    obviously - not running under GC. Under refcounting, if you didn't
    declare your property nonatomic, you're gonna take a lock during dealloc
    to do setMyVar:nil.



    --------------------------

    RONZILLA
  • Am Mi,08.10.2008 um 17:49 schrieb Lee, Frederick:

    > Assuming the following:
    >
    >
    >
    > @property(retain) myVar;
    >
    > ...
    >
    > @synthesize myVar;
    >
    >
    >
    > ...
    >
    >
    >
    > -(void) dealloc {
    >
    > // Can I use:
    >
    > self.myVar = nil;
    >
    > // versus:
    >
    > [myVar release];  //  ?
    >
    > }
    >
    >
    >
    >
    >
    > I've seen examples of using [myVar release].  But doesn't setting
    > myVar
    > = nil does the same thing?
    >
    >
    >
    > Which is the preferred way?
    A never-ending story …

    I prefer self.prop = nil (self setProp:nil]).

    Some ideas:

    1. Disadvantage: In a logical sense, you are on to deconstruct the
    object. So you can say, that it is not valid anymore and you are not
    allowed to send $anything to that object. I think, that you are inside
    the class and can handle this.

    2. Disadvantage: You have to take care: side-effects! Think of undoing
    inside the setter. You probably do not want to register this operation
    for undoing. (Undo would fail, because the object is deconstructed.)

    3. Advantage: Sometimes to care for consistency of your model inside a
    setter. And in this case I want to have this work done on
    deconstruction. If you just release it, maybe this work is never done
    by accident.

    In must, most cases, especially when using @synthesize, it does not
    matter …

    Cheers

    >
    >
    >
    >
    > Ric.

    Amin Negm-Awad
    <negm-awad...>
  • On Oct 8, 2008, at 8:49 AM, Lee, Frederick wrote:

    > I've seen examples of using [myVar release].  But doesn't setting
    > myVar
    > = nil does the same thing?
    >
    To be clear, I assume you mean self.myVar = nil.
    Neither, though "does the same thing".

    > Which is the preferred way?
    >
    Best practice is to use release directly, since this is lower overhead
    (especially if your accessor is atomic) and avoids the possibility of
    unwanted side-effects (especially if a subclass happens to override
    your set accessor).

    The one place where you can't avoid this at the moment, though, is if
    you're using synthesised instance variables: you can't currently
    access the synthesised variable directly, so you will have to use the
    accessor method:

    @interface MyClass : NSObject
    {}
    @property (retain) NSString *aString;
    @end

    @implementation MyClass
    @synthesize aString;
    -(void)dealloc {
        self.aString = nil;  // [aString release]; won't work
    }

    mmalc
  • Am Mi,08.10.2008 um 18:09 schrieb Lee, Frederick:

    > I've been setting my property thusly:
    >
    >
    >
    > @property (nonatomic, retain) myVar;
    >
    >
    >
    > ...what about:
    >
    >
    >
    > @property (nonatomic, copy) myVar; ?
    In this case (deallocation) it doesn't matter, because you set nil.
    [nil copy] is nil.

    Cheers

    >
    >
    >
    >
    > Ric.
    >
    >
    >
    > From: Ron Lue-Sang [mailto:<luesang...>]
    > Sent: Wednesday, October 08, 2008 11:06 AM
    > To: Lee, Frederick
    > Cc: <cocoa-dev...>
    > Subject: Re: In dealloc(): ref @property, Can I use "<property
    > object> =
    > nil; " vs "[<property object> release]; " ?
    >
    >
    >
    >
    >
    > On Oct 8, 2008, at 8:49 AM, Lee, Frederick wrote:
    >
    >
    >
    >
    >
    > Assuming the following:
    >
    >
    >
    > @property(retain) myVar;
    >
    > ...
    >
    > @synthesize myVar;
    >
    >
    >
    > ...
    >
    >
    >
    > -(void) dealloc {
    >
    > // Can I use:
    >
    > self.myVar = nil;
    >
    > // versus:
    >
    > [myVar release];  //  ?
    >
    > }
    >
    >
    >
    >
    >
    > I've seen examples of using [myVar release].  But doesn't setting
    > myVar
    > = nil does the same thing?
    >
    >
    >
    > Which is the preferred way?
    >
    >
    >
    > I prefer doing [myVar release]. Mainly because I don't want setMyVar
    > getting called during dealloc. And by this time there *shouldn't* be
    > any
    > KVO observers for myVar (assuming the property was observed at all
    > before).
    >
    >
    >
    > Yea yea - you've done @synthesize here so we know that the setter
    > doesn't do any custom work. But since we're in dealloc, we are -
    > obviously - not running under GC. Under refcounting, if you didn't
    > declare your property nonatomic, you're gonna take a lock during
    > dealloc
    > to do setMyVar:nil.
    >
    >
    >
    >
    > --------------------------
    >
    > RONZILLA

    Amin Negm-Awad
    <negm-awad...>
  • My environment is certain '...apple-based mobile phone' that is
    nonatomic.

    So all my iVars are accessed via:
    @property(nonatomic, retain) iVar; // array, dictionary, etc. <--
    collections & objects.

    Also, I'm not subclassing these properties.

    I've seen examples of releasing the iVars & setting their pointers to
    nil.

    So I figure, using the self.iVar = nil;

    So you say:
    1) use the [iVar release] directly; yet
    2) use the "self.iVar = nil" approach for 'synthesized instance
    variables.'

    So if I understand correctly, what you're saying is that in my
    particular circumstance (nonatomic),
    (and I'm synthesizing collections, strings & objects)
    the preferred way is setting the 'self.iVar' to nil; per your example
    below.

    Correct?

    Ric.

    -----Original Message-----
    From: mmalc crawford [mailto:<mmalc_lists...>]
    Sent: Wednesday, October 08, 2008 11:26 AM
    To: Lee, Frederick
    Cc: <cocoa-dev...>
    Subject: Re: In dealloc(): ref @property, Can I use "<property object> =
    nil; " vs "[<property object> release]; " ?

    On Oct 8, 2008, at 8:49 AM, Lee, Frederick wrote:

    > I've seen examples of using [myVar release].  But doesn't setting
    > myVar
    > = nil does the same thing?
    >
    To be clear, I assume you mean self.myVar = nil.
    Neither, though "does the same thing".

    > Which is the preferred way?
    >
    Best practice is to use release directly, since this is lower overhead
    (especially if your accessor is atomic) and avoids the possibility of
    unwanted side-effects (especially if a subclass happens to override
    your set accessor).

    The one place where you can't avoid this at the moment, though, is if
    you're using synthesised instance variables: you can't currently
    access the synthesised variable directly, so you will have to use the
    accessor method:

    @interface MyClass : NSObject
    {}
    @property (retain) NSString *aString;
    @end

    @implementation MyClass
    @synthesize aString;
    -(void)dealloc {
        self.aString = nil;  // [aString release]; won't work
    }

    mmalc
  • On Oct 8, 2008, at 9:41 AM, Lee, Frederick wrote:

    > So all my iVars are accessed via:
    > @property(nonatomic, retain) iVar; // array, dictionary, etc. <--
    > collections & objects.
    > Also, I'm not subclassing these properties.
    > I've seen examples of releasing the iVars & setting their pointers to
    > nil.
    > So I figure, using the self.iVar = nil;
    >
    No, that is not Apple-sanctioned best-practice.

    > So you say:
    > 1) use the [iVar release] directly; yet
    > 2) use the "self.iVar = nil" approach for 'synthesized instance
    > variables.'
    >
    Yes, for synthesized *instance variables*.

    > So if I understand correctly, what you're saying is that in my
    > particular circumstance (nonatomic),
    >
    'nonatomic' has nothing to do with it.

    > (and I'm synthesizing collections, strings & objects)
    > the preferred way is setting the 'self.iVar' to nil; per your example
    > below.
    > Correct?
    >
    No.  I stated specifically "synthesized *instance variables*" and gave
    an example:

        @interface MyClass : NSObject
        {} // **** Note: no instance variables
        @property (retain) NSString *aString;
        @end

        @implementation MyClass
        @synthesize aString;
        -(void)dealloc {
              self.aString = nil;  // [aString release]; won't work
        }
        @end

    If instead you had an explicit instance variable:

        @interface MyClass : NSObject {
              NSString *aString;
        }
        @property (retain) NSString *aString;
        @end

    then you would use:

        @implementation MyClass
        @synthesize aString;
        -(void)dealloc {
            [aString release];
        }
        @end

    mmalc
  • Thank you.
    I'm understand.
    Shall remedy.
    Ric.

    -----Original Message-----
    From: mmalc crawford [mailto:<mmalc_lists...>]
    Sent: Wednesday, October 08, 2008 11:56 AM
    To: Lee, Frederick
    Cc: <cocoa-dev...>
    Subject: Re: In dealloc(): ref @property, Can I use "<property object> =
    nil; " vs "[<property object> release]; " ?

    On Oct 8, 2008, at 9:41 AM, Lee, Frederick wrote:

    > So all my iVars are accessed via:
    > @property(nonatomic, retain) iVar; // array, dictionary, etc. <--
    > collections & objects.
    > Also, I'm not subclassing these properties.
    > I've seen examples of releasing the iVars & setting their pointers to
    > nil.
    > So I figure, using the self.iVar = nil;
    >
    No, that is not Apple-sanctioned best-practice.

    > So you say:
    > 1) use the [iVar release] directly; yet
    > 2) use the "self.iVar = nil" approach for 'synthesized instance
    > variables.'
    >
    Yes, for synthesized *instance variables*.

    > So if I understand correctly, what you're saying is that in my
    > particular circumstance (nonatomic),
    >
    'nonatomic' has nothing to do with it.

    > (and I'm synthesizing collections, strings & objects)
    > the preferred way is setting the 'self.iVar' to nil; per your example
    > below.
    > Correct?
    >
    No.  I stated specifically "synthesized *instance variables*" and gave
    an example:

        @interface MyClass : NSObject
        {} // **** Note: no instance variables
        @property (retain) NSString *aString;
        @end

        @implementation MyClass
        @synthesize aString;
        -(void)dealloc {
              self.aString = nil;  // [aString release]; won't work
        }
        @end

    If instead you had an explicit instance variable:

        @interface MyClass : NSObject {
              NSString *aString;
        }
        @property (retain) NSString *aString;
        @end

    then you would use:

        @implementation MyClass
        @synthesize aString;
        -(void)dealloc {
            [aString release];
        }
        @end

    mmalc
  • On 10/8/08 9:55 AM, mmalc crawford said:

    > No, that is not Apple-sanctioned best-practice.

    mmalc,

    That was a nice summary, thanks.

    So does the same advice apply for init methods?  That is: set ivars
    directly (unless there is no ivar, in which case you have no choice but
    to call the setter).

    Cheers,

    --
    ____________________________________________________________
    Sean McBride, B. Eng                <sean...>
    Rogue Research                        www.rogue-research.com
    Mac Software Developer              Montréal, Québec, Canada
  • On Oct 8, 2008, at 10:16 AM, Sean McBride wrote:

    > That was a nice summary, thanks.
    >
    Cheers.

    > So does the same advice apply for init methods?  That is: set ivars
    > directly (unless there is no ivar, in which case you have no choice
    > but
    > to call the setter).
    >
    Yes.

    mmalc
  • Your answer got me thinking about Synthesized versus Explicit Instance
    Variables.

    I've been using Synthesized-Explicit Instance Variables.
    That is, explicitly declaring iVars AND per ObjC_2, using
    @property/@synthesize
    directive to build the assessors.

    Is there any benefit of using non-explicit/Synthesized Instance
    Variables that you had mentioned?

    Ric.

    -----Original Message-----
    From: mmalc crawford [mailto:<mmalc_lists...>]
    Sent: Wednesday, October 08, 2008 11:56 AM
    To: Lee, Frederick
    Cc: <cocoa-dev...>
    Subject: Re: In dealloc(): ref @property, Can I use "<property object> =
    nil; " vs "[<property object> release]; " ?

    No.  I stated specifically "synthesized *instance variables*" and gave
    an example:

        @interface MyClass : NSObject
        {} // **** Note: no instance variables
        @property (retain) NSString *aString;
        @end

        @implementation MyClass
        @synthesize aString;
        -(void)dealloc {
              self.aString = nil;  // [aString release]; won't work
        }
        @end

    If instead you had an explicit instance variable:

        @interface MyClass : NSObject {
              NSString *aString;
        }
        @property (retain) NSString *aString;
        @end

    then you would use:

        @implementation MyClass
        @synthesize aString;
        -(void)dealloc {
            [aString release];
        }
        @end

    mmalc
  • --- On Wed, 10/8/08, Lee, Frederick <Frederick.Lee...> wrote:

    > Your answer got me thinking about Synthesized versus
    > Explicit Instance
    > Variables.
    >
    > I've been using Synthesized-Explicit Instance
    > Variables.
    > That is, explicitly declaring iVars AND per ObjC_2, using
    > @property/@synthesize
    > directive to build the assessors.
    >
    > Is there any benefit of using non-explicit/Synthesized
    > Instance
    > Variables that you had mentioned?

    Those are synthesized *accessors*. Synthesized *instance variables*, which mmalc was talking about, are a feature of the 64-bit Objective-C runtime where the @synthesize directive can create instance variables that aren't declared in the interface.

    Cheers,
    Chuck
  • On 10/8/08 10:21 AM, mmalc crawford said:

    >> So does the same advice apply for init methods?  That is: set ivars
    >> directly (unless there is no ivar, in which case you have no choice
    >> but
    >> to call the setter).
    >>
    > Yes.

    One last related question, if I may.

    What about awakeFromInsert/awakeFromFetch?  If my entity has an
    attribute named 'firstName', should I use the (magically pre-existing)
    method setFirstName: or should I use setPrimitiveValue:forKey:?

    Cheers,

    --
    ____________________________________________________________
    Sean McBride, B. Eng                <sean...>
    Rogue Research                        www.rogue-research.com
    Mac Software Developer              Montréal, Québec, Canada
  • On Oct 8, 2008, at 4:44 PM, Sean McBride wrote:

    > What about awakeFromInsert/awakeFromFetch?  If my entity has an
    > attribute named 'firstName', should I use the (magically pre-existing)
    > method setFirstName: or should I use setPrimitiveValue:forKey:?
    >
    "If you want to set attribute values in an implementation of
    [awakeFromInsert/awakeFromFetch], you should typically use primitive
    accessor methods (either setPrimitiveValue:forKey: or—better—the
    appropriate custom primitive accessors). This ensures that the new
    values are treated as baseline values rather than being recorded as
    undoable changes for the properties in question."

    (Forthcoming.)

    mmalc