Cocoa release / auto-confusion for iphone

I am slowly teaching myself cocoa for the iPhone (via the Stanford Class on iTunes U ) and I just left through the memory management part and I would like to hope to get some confirmation that the assumptions I make about how the memory is processed and how [release] and [autoadvertising] work. Since memory management is really a basic and fundamental, but very important part of the programming experience, I would like to make sure that I am doing it right.

I understand that you need to free everything related to alloc, new or copy.
If I do this:

NSString *temp = [[NSString alloc] initWithString:@"Hello World"]; 

Then I need to add [temp release / autorelease] in the end, since I have alloc.

However, if I do this:

 NSString *temp = @"Hello World"; 

Then it doesn't seem to need a release statement. Does the NSString class call automatically as part of the destination?

Also, is there a difference between the two temp objects here after these statements? They both contain the same string, but are there any memory / usage ways in which they differ?

Secondly, with properties, I assume that the abstract is processed automatically. If I have this:

 @interface Person : NSObject { //ivars NSString *firstName; NSString *lastName; } //properties @property NSString *firstName; @property NSString *lastName; ///next file @implementation Person @synthesize firstName; @synthesize lastName; - (void) dealloc { //HERE!!!! [super dealloc]; } 

I assume that I do not need to add [firstName release] and [lastName release] (in // HERE !!!!), since this is automatically handled by the properties. It is right?

I understand that if I do this in code (assuming I defined initWithFirstName):

 Person *Me = [[Person alloc] initWithFirstName: @"Drew", lastName:"McGhie"]; 

that later I will have to use [Me release / autorelease];

Any help confirming or correcting my understanding is greatly appreciated.

RECORDING ANSWERS ANSWERS

I thought I would write all this by going through all the answers and testing the suggestions and telling about what worked.

I need to add [firstName release], [lastName release], but I also need to add (save) to the property descriptions. Do not add (save) triggered warnings, as it assumes (assign). This is how I finally set up the class

 @interface Person : NSObject { //ivars NSString *firstName; NSString *lastName; } //properties @property (retain) NSString *firstName; @property (retain) NSString *lastName; ///next file @implementation Person @synthesize firstName; @synthesize lastName; - (void) dealloc { [firstName release]; [lastName release]; [super dealloc]; } 
+5
source share
6 answers

The rule is simple: if you alloc , copy or retain , it is your responsibility to release . If you have not done so, it is not. However, if you need to rely on an object nearby, you must retain (and subsequently release ).

We can process the string literal according to the rules - you do not need release because you do not own it. So simple; no need to worry about whether they are special cases or not, just follow the rules and everything will be fine.

I wrote a blog post with a collection of articles about Cocoa's memory management rules ; I would recommend following some of the links.

+10
source
  • I have never issued string constants like NSString *foo = @"x"; . Logically, if you got the release result of this, you would have to release the initWithString parameter, and both parameters would be initWithFirstName:lastName: too.
  • You must do release or autorelease firstName and lastName . I saw warnings that I did not use property syntax in destructors, and I think the same reason that you do not use virtual functions in C ++ constructors and destructors.

Your guess was wrong. You should do the following:

  Person *Me = [[Person alloc] initWithFirstName: @"Drew" lastName: @"McGhie"]; ... [Me release]; 

or that:

  Person *Me = [Person personWithFirstName: @"Drew" lastName: @"McGhie"]; 

... and make sure your Person object handles +personWithFirstName:lastName: correctly, i.e. [[[self alloc] initWithFirstName: firstName lastName: lastName] autorelease] .

You should probably do this with less code. Clarity is important, NSAutoreleasePool will probably never be your bottleneck, and if it is ever easily fixed.

I think that people make a lot of efforts to avoid class messages that return an autorelease 'd object, which simply does not deserve attention. This is a premature optimization in which it is probably not needed and may not even be the right thing. And it's harder to maintain, you are more likely to pursue the leak forever.

In addition, you will go to the autorelease object that you should have init (i.e. alloc + initPersonWithFirstName:lastName: instead of using a class message such as personWithFirstName:lastName: ). I suggest you do it immediately, otherwise you are potentially pursuing the same leak. Therefore, if you do not add the personWithFirstName:lastName: method to Person , do this instead:

  Person *Me = [[[Person alloc] initWithFirstName: @"Drew" lastName: @"McGhie"] autorelease]; 

Summary: Cocoa helps you a lot in memory management. Make sure you do not fight.

Updated based on Jon's comments.

+3
source

NSStrings created with @"String here" syntax are persistent strings. They are different from regular strings. Like regular C constant strings, they are created when your program loads and exists throughout its life. The NXConstantString class to which they belong ignores all memory management messages. You can retain and release them all that you like, and it will not make any difference.

For a string created using the [[NSString alloc] initWith...] -type method, normal memory management rules apply . I highly recommend reading related documents - they are not complicated, and after reading them you will find out almost everything you will ever need to know about Cocoa's memory management.

+2
source

The last part is the first: you really need an Auto / Release Me . However, you also need to add [firstName release]; and [lastName release]; at -dealloc ; or better yet; self.firstName = nil;

As for string literals; this part gets a little hairy, but [@"String literal" release] is essentially noop. Thus, there is a difference between the two temporary objects, but as you usually don’t know who you will be dealing with by adding [temp release]; It is usually a safe choice if you do not know that it will contain an auto-implemented object.

+1
source

About firstName / lastName.

You should always, for clarity, remember to specify property attributes. The default setter attribute is assigned, in which case you want to use persistence.

 @interface Person : NSObject { NSString *firstName; } @property (retain) NSString *firstName; @end 

When saving each and only time, when you use dot notation to assign a value, the compiler inserts a save: just remember to always use it. For consistency, I advise you to write your initializer as follows:

 - (id) initWithFirstName:(NSString*) aString { self.firstName = aString; } 

and the dealloc method as follows:

 - (void) dealloc { self.firstName = nil; } 

About objects of type @ "" - type. They are persistent objects of NSStrings. Just use them as NSString objects (they) and never release them. The compiler takes care of them.

+1
source

Is the NSString class automatically auto-advertised as part of the destination?

The NSString class did nothing because you did not send a message to it. Everything you did was assigned to a variable. NSString does not find out about this, and this is not his business.

Also, is there a difference between the two temp objects here after these statements? They both contain the same string, but are there any memory / usage ways in which they differ?

They are both NSStrings, they both contain the same value, and both are considered immutable. That’s all you have to take care of.

Secondly, with properties, I assume that the abstract is processed automatically. If I have this:

 @property NSString *firstName; @property NSString *lastName; - (void) dealloc { //HERE!!!! [super dealloc]; } 

I assume that I do not need to add [firstName release] and [lastName release] (at //HERE!!!! ), since this is automatically handled by the properties. It is right?

Not. NSObject does not give you all of your property values; you still need to free them there.

Also, do not do self.firstName = nil and self.lastName = nil in dealloc . They are converted to messages (to your access methods), and when you do this in dealloc , you send messages to the half- dealloc ked object. It takes trouble. The same applies to initializing property values ​​in init . Using your properties / accessors, you send messages to the init object.

+1
source

Source: https://habr.com/ru/post/888516/


All Articles