iPhone memory management (with specific examples/questions)

前端 未结 3 1778
醉梦人生
醉梦人生 2020-12-20 00:58

Hey all. I know this question\'s been asked but I still don\'t have a clear picture of memory management in Objective-C. I feel like I have a pretty good grasp of it, but I\

相关标签:
3条回答
  • 2020-12-20 01:21

    Ideally you would want to use the accessors whenever possible, especially when dealing with objects as they help avoid many memory issues. So even for instance variables, you should do:

    self.fooArray = ...;
    

    instead of

    fooArray = ...;
    

    The reason why you should declare properties for object instance variables is because the memory management is slightly more complicated, and recreating it by hand each time is tricky. The correct setter for a nonatomic, retained property would look like:

    - (void)setFoo:(NSArray *)aFoo {
        if (foo == aFoo) {
            return;
        }
        NSArray *oldFoo = foo;
        foo = [aFoo retain];
        [oldFoo release];
    }
    

    You are right about the instance variable having a retain count of 2 when you do something like this (assuming foo is retained):

    self.foo = [[NSMutableArray alloc] init];
    

    The first retain count is coming from alloc, and the second one from your synthesized setter. Any of these should work:

    // longer, explicit version, releases immediately (more efficient)
    NSMutableArray *aFoo = [[NSMutableArray alloc] init];
    self.foo = aFoo;
    [aFoo release];
    
    // autoreleased, not so bad unless you're a memory management freak
    self.foo = [[[NSMutableArray alloc] init] autorelease];
    
    // an even shorter version of the above
    self.foo = [NSMutableArray array];
    

    To create private properties, you can declare them as a class extension in the .m implementation file. To give an example, consider a simple Person object, which has a name, and a boolean property didSave which simply indicates whether the object has been saved to some database or not. Since we don't want to expose this to the outside world, but still keep the benefits of properties inside the implementation file, we can create the header file will all instance variables (public, private, protected) and only public properties:

    // Person.h
    
    @interface Person {
        NSString *name;
    
        @private
        BOOL didSave;
    }
    
    @property (nonatomic, retain) NSString *name;
    
    @end
    

    But declare private properties inside the implementation:

    // Person.m
    
    // property is declared as a class extension, making it 
    // invisible to the outside world.
    @interface Person ()
        @property BOOL didSave;
    @end
    
    @implementation
    
    // synthesize as normal
    @synthesize name, didSave;
    
    @end
    
    0 讨论(0)
  • 2020-12-20 01:38

    According to Apple's Object Ownership Policy, any method that begins with the words alloc or new, or contains copy is owned by the caller.

    To obtain ownership of an object, you must retain it.

    So, in your first example, the retain is unnecessary because you already own the object.

    The correct way to do this:

    fooArray = [[NSMutableArray alloc] init];
    

    Since autoreleased objects are owned by the current autorelease pool, you must call retain on them to gain ownership of them, so this example is correct:

    fooString = [[NSString stringWithFormat:@"%d items", someInt] retain];
    

    This would work fine as well:

    self.fooString = [NSString stringWithFormat:@"%d items", someInt]; //retained by property setter
    

    And for your last example using the property setter, this would be the correct way to do it:

    NSMutableArray *anArray = [[NSMutableArray alloc] init];
    self.fooArray = anArray;
    [anArray release];
    

    Instead of having to do the above, I'd suggest the following solution:

    self.fooArray = [NSMutableArray arrayWithCapacity:10];
    

    arrayWithCapacity: will return an autoreleased NSMutableArray, which is the retain-ed by the property setter method. :)

    0 讨论(0)
  • 2020-12-20 01:42

    First of all, with this line:

    fooArray = [[NSMutableArray alloc] init];
    

    fooArray will automatically have a retain count of 1.

    Second, yes, it's 2. And your guess on the setter implementation is correct.

    Third, the latter one is right

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