Acceptable ways to release a property

后端 未结 4 513
滥情空心
滥情空心 2020-12-19 12:31

Assume there is a class with the following interface:

#import 

@interface MyClass :          


        
相关标签:
4条回答
  • 2020-12-19 12:50

    First, if you want to avoid the alloc, release, autorelease etc... you can call a date factory method which doesn't start with alloc.

    For example: self.myDate = [NSDate date];

    The date class factory method does an autorelease according to the convention rules. Then the property retains it.

    1. Alloc will give it a retain count of 1, then assigning the property will retain it. Since your class is now retaining it from the property, you can release it to counter act the alloc.

    2. Ditto but that's a wierd round about way to do it.

    3. 3 is equivalent to the code I had above ([NSDate date]);

    4. In this case, the property will retain it (after alloc incremented the retain count), then you're going under the covers to decrement it. Works but I wouldn't recommend doing that since you're synthesized (retain) property will do that for you.

    0 讨论(0)
  • 2020-12-19 12:51

    the pattern of release and renew is merely a semantic. You get a retain count for each of the following.

    myObject = [Object alloc]
    objectCopy = [myObject copy]
    myNewObject = [Object newObjectWithSomeProperties:@"Properties"] // Keyword here being new
    // And of course
    [myObject retain]
    

    a property with the modifier (retain) or (copy) will have retain count on it. the backing store _myDate is merely where the object is actually stored.

    when you get a retain count you need to release. Either immediately with the [myObject release] message or let the pool release it with [myObject autorelease]

    Whatever the case, Any retain you are given (implicit or explicit) will need to be released. Otherewise the garbage collector will not collect your object and you will have a memory leak.

    the most common usage in

    Object myObject = [[[Object alloc] init] autorelease]; // Use this when you dont plan to keep the object.
    
    Object myObject = [[Object alloc] init];
    self.myProperty = [myObject autorelease]; // Exactally the same as the Previous. With autorelease
                                             // Defined on the assignment line.
    
    self.myProperty = [[[Object alloc] init] autorelease]; // Same as the last two. On one line.
    

    I will demonstrate other possibilities

    // Uncommon. Not incorrect. But Bad practice
    myObject = [[Object alloc] init];
    self.myProperty = myObject;
    
    // Options
    [_myProperty release] // Bad practice to release the instance variable
    [self.myProperty release] // Better practice to Release the Property;
    
    // releasing the property or the instance variable may not work either.
    // If your property is using the (copy) modifier. The property is copied rather then retained.
    // You are still given a retain count.
    // But calling release on a copy will not release the original
    
    [myObject release]; // Best Practice. Good when Threading may run the autorelease pool
    [myObject autorelease]; // As good as the previous. 
                            // But may leave your object in memory during long operations
    

    Essentially, your object given a retain will be the same object in the Property the Variable and the Instance Variable. Releasing on any of them will release it. However. Best practice says that if you retain an object. Best to call release on the same variable of that object. Even if Autorelease and retain is called on the other side.

    // Other items that give you a retain count. Core Media or Core Anything Functions that have Create Or Copy in the name.

    0 讨论(0)
  • 2020-12-19 12:53

    1) Just fine.

    2) Possibly unsafe, and will trigger warnings in the latest LLVM static analyzer. This is because the object returned by the getter method may not be the same one you passed to the setter. (The setter may have made a copy, for example, or may have failed validation and set a nil instead.) This would mean you were leaking the original object and over-releasing the one the getter gave back to you.

    3) Just fine; similar to 1 but the release will come when the current autorelease pool is drained instead of immediately.

    4) Possibly unsafe, but will not trigger warnings that I've seen. The issue is similar to the one described in 2; the object in the ivar may not be the one you passed to the setter.

    5) Safe, but will not use the setter method or notify any observers of the property.

    In the case where the property is a retain type, and both the getter and setter are just the synthesized versions, all of the above examples will work. However, they don't all represent best practice, and may trigger analysis warnings. The goal should be that the -foo method works correctly regardless of how myDate is managing its memory. Some of your examples above don't do that.

    If, for example, you decided to change the property to copy later, you should not be required to change any other code to make it work correctly. In cases 2 and 4, you would be required to change additional code because the foo method is assuming that the setter will always succeed and always set the original object.

    0 讨论(0)
  • 2020-12-19 13:05

    5) is a bug - it leaks the old instance as it doesn't get released but just reassigned.

    1) is clean and the best way to go. 4) is ok but puts some burden on the memory system - the object might live longer than needed. 2) technically ok, but you shouldn't directly retain/release the property - that's what the syntactic sugar is for! 3) technically ok, but also bypasses the property and relies on implementation details.

    2) and 3) are discouraged and ask for trouble in the future when some part of code changes.

    Edit: New code doesn't leak in 5). It has the same downsides, though.

    There's a reason why we got support for properties, and it does a great and consistent use. You should only consider bypassing them if your time profile gives very clear hints that this is a bottle neck (unlikely).

    0 讨论(0)
提交回复
热议问题