When to use properties in objective C?

后端 未结 2 2057
孤街浪徒
孤街浪徒 2020-12-15 09:36

I have a question here: Confusing double free error message/memory leak in iPhone app which I think needs a new question to answer it.

The code I am interested in i

相关标签:
2条回答
  • 2020-12-15 09:55

    You technically only need to use properties for values that are intended to be accessible from other classes, but many find it easier to use (retained) properties for all pointer-type instance variables so that the retaining is a bit more automatic. (And then use self.propertyName = xxx; notation for setting and self.propertyName = nil; for releasing in dealloc.)

    Yes, you can do the retains and releases "manually", but it's a hair tedious to do so, and you tend to muck things up when you make "quick edits". The one thing you have to watch out for, though, is assigning a retained (not simply autoretained) value (such as your alloc/init values) to a self.xxx property. This will result in double retain, if you don't mitigate it somehow.

    Another thing to do, if you don't use properties, is to always nil a pointer value after you release it. This prevents you from accidentally using the released value and and it prevents you from doing a double release.

    (Note that it's in no way "bad programming" to use "lazy" techniques like I described above, vs "perfectly" figuring out everything. About 98% of programming is debugging, and anything you can do to prevent bugs or make them easier to find is goodness.)

    (I'll also note that your problem in the above code appears to be mainly that you do not nil thetdest et al pointers after releasing them. And your if tests should likely check to see if the pointer has been nilled before using it.)

    Added: Note that the above applies to pre-ARC programs. With ARC the "rules" change substantially.

    0 讨论(0)
  • 2020-12-15 10:00

    Properties do a lot of things. At the most superficial level, they let you access your member variables in dotted form. At best, they can be excellent memory management tools (and more).

    Let's say you have a variable:

    NSNumber * myNumber;
    

    Later in the code, you access it as:

    myNumber = [NSNumber numberWithInt: 5];
    

    The problem is that you might lose reference to the previously stored value in myNumber. Possible Memory Leak!! At this point, you don't have a retain on myNumber and it may get dealloc'd before you're done using it.

    How can properties help? Let's say you defined a property around it and used synthesize:

    In the interface definition:

    NSNumber * myNumber;
    ...
    
    @property (retain, nonatomic) NSNumber * myNumber;
    

    and

    In the implementation file:

    @synthesize myNumber;
    

    This will create a getter and setter. Meaning... everytime you assign myNumber to something as in:

    self.myNumber = newNumber;
    

    the following setter method (created by synthesize directive) gets invoked:

    - (NSNumber *) setMyNumber: (NSNumber *) newNumber {
        [myNumber release];
        myNumber = newNumber;
        [myNumber retain];
    
        return newNumber;
    }
    

    Here, myNumber gets a retain automatically. This is very tedious to do by hand everytime... as you can see, it's much easier to use properties.

    This is still not a perfect solution, though! Why? What if you use the following statement in your implementation:

    myNumber = newNumber;
    

    Remember, properties' getter and setter get invoked only if you're using the dotted notation (self.myNumber). So here, using properties has done nothing for us, 'cause we forgot to use them! This is very common and likely lapse and understandingly frustrating.

    So, what's the best way? This is what I recommend (as do countless others):

    In the interface class:

    NSNumber * _myNumber;
    ...
    @property (retain, nonatomic) NSNumber * myNumber;
    

    In the implementation file:

    @synthesize myNumber = _myNumber;
    

    Now, you can access your-number as:

    self.myNumber = whateverNewNumber;
    

    But, if you did:

    myNumber = whateverNewNumber;
    

    You'll get an error... because myNumber variable just doesn't exist... forcing you to use self.myNumber everytime!

    Also, if you do choose to go this route, don't forget the dealloc:

    - (void) dealloc {
        [_myNumber release];
        _myNumber = nil;
    }
    

    or more succinct:

    - (void) dealloc {
        self.myNumber = nil;
    }
    
    0 讨论(0)
提交回复
热议问题