Hacker News new | past | comments | ask | show | jobs | submit login
How Memory Management Works on iOS (gaiagps.com)
19 points by dsil on May 26, 2011 | hide | past | favorite | 19 comments



3. When you type self.foo = bar, there is an implied retain. If you set a class variable without the "self," there is no implied retain.

No no no no no... That is absolutely incorrect. Only properties declared "retain" do that.

  @property (nonatomic, assign) NSObject *foo;  // doesn't retain
  @property (nonatomic, copy) NSObject *bar;  // doesn't retain
  @property (nonatomic, retain) NSObject *baz;  // *does* retain
(The 'nonatomic' isn't related to the retain/no-retain semantics, but most properties are declared nonatomic, as atomic properties have some locking overhead.)

On a side note, a discussion of iOS/Mac memory management isn't very useful if it doesn't talk about how autorelease pools work.


The same thing applies to "copy" properties. If you do "self.foo = bar;" when foo is a copy property, you have taken ownership of that object, and need to release it later (hopefully by doing "self.foo = nil;".


Similar, but not the same, though yes, releasing it can be done in the same manner.


On the topic of properties, I also find it helpful to define the property and variable to have different names (e.g., NSString _foo; for the variable and @property (nonatomic, copy) NSString foo; for the property). When mapped through @synthesize foo = _foo;, it avoids confusion about the memory management necessary for a particular value.


You are right, I will correct it.

Also, hopefully this post is useful as is at least for beginners, though adding information on autorelease pools would be good for sure.


Apple's Memory Management Programming Guide: http://developer.apple.com/library/mac/#documentation/Cocoa/...


This:

  - (void) setFoo:(NSString*) bar {
    [foo release]; 
    foo = [bar retain]; 
  }
should be:

  - (void) setFoo:(NSString*) bar {
    if(bar == foo)
       return;
    [foo release]; 
    foo = [bar retain]; 
  }
so that you can do without crashing:

  obj.foo = obj.foo;


In the same line of thinking, for object that don't hold memory space I need to mark on the spot, I use :

  - (void) setFoo:(NSString*) bar {
    [foo autorelease]; 
    foo = [bar retain]; 
  }
which I expect to do nothing (retain count is unchanged) when foo == bar. I do it for concision, am I missing something?


The cleanest version IMO is

  - (void) setFoo:(NSString*)bar {
    [bar retain];
    [foo release]; 
    foo = bar;
  }
which harmlessly increments and decrements for self-assignment.


that works fine too and prevents any issues with releasing the variable before it gets retained again. objects might hang around in memory a little longer this way, though (for foos != bars)


That would also work, autorelease is generally considered slow though.


Ah, trickier than I thought. I posted an EDIT to the blog post.


> 2. When you type "alloc" there is an implied retain.

It's not quite that simple. The official rule from Apple's Memory Management Programming Guide most succinctly states "You take ownership of an object if you create it using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message."


This article gives bad advice. If you use his examples your program will crash; see tylerc230's comment. Also, it does not follow generally accepted style practices, such as the lack of a space after a closing bracket [[like]this].


> “Typing self.foo releases and nils the variables.” Yes, if it’s a retain or copy property.

> “Just typing foo = nil is a memory leak.” Yes, if you had retained the object, but not if it were a weak reference. Admittedly, this is a semi-rare scenario.


it also help when you understand how the dot-notation works in objective-c... it's not like other languages where you are just accessing a member of an object.

    foo = object.bar;
    is syntactic sugar for
    foo = [object bar]; //where 'bar' is a method call
and

    object.foo = bar;
    is syntactic sugar for:
    [object setFoo:bar];
I dealt with a lot of goofy memory errors trying to figure out why using 'self.foo' and just 'foo' inside of a class acted differently. Now it makes much more sense.


A lot of developers (myself included) don't use the dot syntax for property access for this reason and another:

x.foo = z; becomes an ambiguous statement in obj-c when you use dot access. Is x an object? then this is a message send. Is x a struct? then this is an assignment.

Typically in my interface file, I explicitly define my member variables with a leading '_';

@interface Foo { NSObject_bar; }

@property(nonatomic, retain) NSObject bar;

@implementation Foo @synthesize bar=_bar; @end

And if I want to access bar I use [x bar], [x setBar:y]; it is easy to visually scan for direct use of member values by looking for the leading '_'


Good article, though it kinda violates rule #1 of Cocoa memory management: don't try to summarize the rules, because you'll probably miss a subtlety. Link to the Apple docs instead.


I lived in doubt of my code until I decided to fully understand memory management. Now that I understand it, it seems simple enough to summarize... but thats the trick




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: