setter, @synthesize etc...

Discussion in 'iPhone/iPad Programming' started by MACloop, Jul 7, 2010.

  1. macrumors 6502

    I have read and thought some about setters and getters lately and maybe someone can clear this out for me.

    I am using the following syntax:

    NSMutableArray *list;
    @property(nonatomic, retain)NSMutableArray *list;
    self.list = someList;
    What about if I for instance would like to change the array later on in my code. I have noticed that both these following examples are actually working. Which one is correct and why? (I have been using the first one because I thought the self. makes the object retain +1...)
    [list removeAllObjects];
    [self.list removeAllObjects];
    the same thing appears by getting values aswell, like:
    someList = list;
    somelist = self.list;
  2. macrumors 6502


    You can't actually change an NSArray after you've initiated it. That's what the NSMutableArray class is for...
  3. Moderator


    Staff Member

    Given that he is using a NSMutableArray this comment is not particularly helpful!

    Personally I would say you should use
    [self.list removeAllObjects];
    somelist = self.list;
    Whilst it may not seem like there is any reason to if you don't do this then you may have weird behaviour if there is a subclass involved. The subclass could override the getter to do some work to generate/calculate the ivar value on demand instead of storing it in the property variable used by the superclass. All superclass methods should work correctly with the subclass but if you shortcut the access they would not.

    In general good O-O programming discipline says to always use the setter/getter methods (and therefore dot syntax) when accessing ivars. This includes access within the class itself.
  4. macrumors 6502




    Sorry, I'll give reading-the-actual-post a try next time...
  5. macrumors 6502

    actually it is she ;-)

    Ok that makes sense!
  6. macrumors 6502

    By the way, this was just a "dummy" example to concrete explain my issue...
  7. Moderator


    Staff Member

    Sorry! MACloop doesn't really give much away and typing he/she all the time is a bit long winded. I will remember for the future.
  8. macrumors 6502

    No problem :)
  9. macrumors 6502


    I like to do things like this, just to be really clear about what is going on.

    NSMutableArray *list_;
    @property(nonatomic, retain)NSMutableArray *list;
    @synthesize list = list_;
  10. macrumors 6502

    OK, that is interesting! I have seen it in tutorials and other code snippets on the web. So futher in your code, are you using list...or self.list when setting and getting values to this variable? And how do you do in viewDidUnload and dealloc?

  11. macrumors 6502


    In general the only place you would see list_ in my code is in the header where I declare it
    NSMutable *list_;
    But occasionally I like to make a read only property when I know that other objects will never have to set the property but only retrieve it. So I would do this.
    NSArray *list_;
    @property (nonatomic, readonly) NSArray *list;
    - (NSArray*)list {
        if(list_ == nil) {
            list_ = [NSArray arrayWithObjects:@"one",@"two",nil];
        return list_
    The advantage of this is that if I receive a memory warning I can get rid of the property easily enough by setting it to nil, and I know that it will be there when I need it again, because as soon as I use it it will be re-instantiated. I don't know if it is the right and standard way to do lazy loading, but it seems to work well enough for me so far.

    So basically the only time I would ever refer to the ivar (list_) directly would be in the property's setter or getter. If you refer to the property (self.list) inside the setter or getter, there is a good chance you will hit an infinite loop, right?
  12. macrumors 68030


    You're missing a retain in your list method.

    How do you set the property to nil?
  13. Moderator


    Staff Member

  14. macrumors 6502


    Your absolutely right about the retain, and I guess by property I ment ivar. So I would release and nil it? Does that make sense?

    Also true!
  15. macrumors 68040


    One point on this:

    When you @synthesize a retained property (like in the example you listed):
    - the setter will retain +1 the object you pass in (and release the previous value.
    - the getter will NOT retain +1 the value it returns. The caller can retain it for itself if it wants to keep it around. (Well, actually it *could* return an autoreleased object, but the calling code should not count on that or care either way.)

    self.list = someList; // setter called; value is stored in list and retained +1
    [self.list removeAllObjects]; // getter called; object is not retained +1

    Also, I agree with others who say to always use the setters/getters. (e.g., use self.list, not list) -- the only exception to this is when you implement your own setters or getter rather than @synthesize (obviously if the setter calls the setter, you've got an infinite loop on your hands).

    You don't always have to, of course. But you'll save yourself occasional mistakes if you do.

    I even use setters in [dealloc] to release retained properties. e.g.,
    self.list = nil;
    [super dealloc];
  16. macrumors 6502

    Thanks for the answer! I have read though that it might be against Apple's recommendations to use setters in dealloc. The problem might be that you (with calling the setter) could use a setter in an already partially deallocated object. Therefor I have been using
     [list release];
    in the dealloc but this is perhaps not neccesary?
  17. macrumors 68030


    It is recommended that you not use the setter in dealloc. It's more of an issue if you are writing library code or classes that are intended to be subclassed.

    There was a bug of this kind in 2.x where UIViewController set its view property in its dealloc method using the setter. This would call any overridden setView methods in UIViewController subclasses after the subclass had called super dealloc. Overriding setView was part of the recommended way to clean up outlets at that time, before viewDidUnload was available.

    There is no advantage at all to using the setter in dealloc.
  18. macrumors 68040


    Yeah, that's a good point about using setters in dealloc and subclasses.

    Sorry for the bad advice. I take back what I said about using setters in dealloc. :)

Share This Page