How does implementation work work in Objective-C?

I just read the manual Practical memory management .

I am a little confused by this block of code:

- (void)printHello { NSString *string; string = [NSString stringWithFormat:@"Hello"]; NSLog(@"%@", string); } 

It seems to me that the string will have a reference count of 0. Is this true?

What causes a string to be freed before we call NSLog(string) ?

This is somehow equivalent to this:

 - (void)printHello { NSString *string; string = [[[NSString stringWithFormat:@"Hello"] retain] autorelease]; NSLog(@"%@", string); } 

Change Similarly, this code is provided in the Practical Memory Management Guide:

 - (NSString *)fullName { NSString *string = [NSString stringWithFormat:@"%@ %@", firstName, lastName]; return string; } 

When and how is the return value freed? Who is the owner? Does the caller fullName call the string returned by the full name?

+6
memory objective-c iphone
source share
2 answers

Strictly speaking,

 - (void)printHello { NSString *string; string = [NSString stringWithFormat:@"Hello"]; NSLog(@"%@", string); } 

Not equivalent

 - (void)printHello { NSString *string; string = [[[NSString stringWithFormat:@"Hello"] retain] autorelease]; NSLog(@"%@", string); } 

The convention is that the method should auto-reclassify any object it returns. The only exception (AFAIK) is for constructors that return an object with a save value of +1. Because [NSString stringWithFormat:] returns an object. In the first fragment, stringWithFormat: returns an already-implemented object. the second fragment, you save it again, and it will be released twice (which has the same effect, but the second save / autoresizing pair is redundant).

Ok now to answer your question. Essentially, every time UIKit calls your code, it creates an NSAutoreleasePool object. Each time you automatically transfer an object, it is added to this pool. Finally, when your code returns to UIKit, it calls the [pool drain] method (ie [pool drain] ) and which frees up every object that has been added to the pool and frees the pool. In addition, autofill pools can be nested, so you can create your own pools and reset them if you are going to create many objects with auto-implementation. It is not as difficult as it seems.

I highly recommend that you read the Autorelease Pools chapter in the memory management guide (which, incidentally, happens right after Practical memory management ).

+7
source share

First of all:

 NSLog(string); 

Do not do this. (I just realized that this comes directly from Apple. Weird documents.) The first argument to NSLog is the format string. If your string contains some percentage of shoots, bad things will happen. Correct if a slightly longer path:

 NSLog(@"%@", string); 

Now: a point with auto-implemented objects does not have a null value. They save the score 1+ and have a pending -1 operation on them, which will be "soon in the future".

The exact meaning of "soon in the future" depends on the situation. If youre on the main topic and there is no additional pool of autoresists in place, autorealized objects will be released at the next runloop iteration. This is not necessary if you have an additional release pool:

 // Let's pretend this is a long loop and you don't want to wait // for the autoreleased objects to be collected by the main pool. for (…) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *foo = [NSString stringWith…]; [pool drain]; // Now foo is no longer valid. } 

As for returned objects with auto-realization, this is one of the main use cases for auto-implementations. You return an object that will soon die, but if the calling user is interested, he can save and take possession of the property. (It seems that if you forgive the image by dropping a bomb with a burning safety fuse. If the calling user is interested, hell extinguished the fuse, saving it.) And if the calling user is not interested, for example, perhaps ignoring the output from or simply using the value to construct any of another object, it does nothing, and the object exits memory:

 - (id) createObject { return [NSString stringWith…]; } - (void) interestedCaller { NSString *value = [[self createObject] retain]; } - (void) notInterestedCaller { [self createObject]; // maybe just interested in side effects NSString *differentString = [NSString stringWithString:[self createObject]]; } 

It is really convenient and makes manual memory management quite enjoyable. You might be interested in the launch cycles and the Objective-C tutorial by Scott Stevenson .

+8
source share

All Articles