简体   繁体   中英

IOS retain , Assign

I observed the following behavior.

Took two property variables.

@property (nonatomic, retain) NSString *stringOne;
@property (nonatomic, assign) NSString *stringTwo;

In .m file written below code..

 NSMutableString *localstring= [[NSMutableString alloc] initWithString:@"test"];
 self.stringOne = localstring;
 NSLog(@"localstring = %d", [string retainCount]);
 NSLog(@"string one retain count = %d", [self.stringOne retainCount]);
 self.stringTwo = localstring;
 NSLog(@"localstring = %d", [localstring retainCount]);
 NSLog(@"string two  retain count = %d", [self.stringTwo retainCount]);

Here localstring retain count is 1 because of alloc. Now i gave self.stringOne = localString.

The retain count of localstring will become two because of retain property of stringOne. Now i gave self.stringTwo = localString.

Even here the localstring retain count is incremented by one. Notice that i have given assign property to stringTwo. Practically the retain count of localstring or stringTwo should not increase by 1 as it is assign property. Please correct me if i am wrong.

Thanks Jithen

Dump the retainCount ; it is useless. http://www.whentouseretaincount.com/

The source of your confusion is in not understanding how pointers work. Modify your code like this:

@interface BBQ:NSObject
@property (nonatomic, retain) NSString *stringOne;
@property (nonatomic, assign) NSString *stringTwo;
@end

@implementation BBQ
- (void) burn
{
    NSMutableString *localstring= [[NSMutableString alloc] initWithString:@"test"];
    self.stringOne = localstring;
    NSLog(@"localstring = %p", localstring);
    NSLog(@"string one = %p", self.stringOne);
    self.stringTwo = localstring;
    NSLog(@"localstring = %p", localstring);
    NSLog(@"string two  = %p", self.stringTwo);
}
@end

It'll spew something like this:

2013-04-11 08:48:13.770 asdffadsfasddfsa[18096:303] localstring = 0x10010aaf0
2013-04-11 08:48:13.772 asdffadsfasddfsa[18096:303] string one = 0x10010aaf0
2013-04-11 08:48:13.772 asdffadsfasddfsa[18096:303] localstring = 0x10010aaf0
2013-04-11 08:48:13.772 asdffadsfasddfsa[18096:303] string two  = 0x10010aaf0

There is only one string instance in play; localstring , stringOne , and stringTwo all hold references to exactly one instance of NSMUtableString .

Thus, you'll see +1 RC of that one string instance for the alloc , +1 for the assignment to the stringOne property and no change for stringTwo .

(RC's should only be reasoned about in terms of deltas; if you retain an object, you need to balance that with a release when you no longer need the object. That the object may be retained by something else is irrelevant.)

When I ran this code:

@interface ViewController ()

@property (nonatomic, retain) NSString *stringOne;
@property (nonatomic, assign) NSString *stringTwo;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self test];
}

- (void)test
{
    NSMutableString *localstring = [[NSMutableString alloc] initWithString:@"test"];
    NSLog(@"localstring (before setting `stringOne` or `stringTwo`) = %d", [localstring retainCount]);
    self.stringOne = localstring;
    NSLog(@"localstring (after setting `stringOne`) = %d", [localstring retainCount]);
    NSLog(@"string one retain count = %d", [self.stringOne retainCount]);
    self.stringTwo = localstring;
    NSLog(@"localstring (after setting `stringTwo`) = %d", [localstring retainCount]);
    NSLog(@"string two retain count = %d", [self.stringTwo retainCount]);
}

@end

I received this console log:

localstring (before setting `stringOne` or `stringTwo`) = 1
localstring (after setting `stringOne`) = 2
string one retain count = 2
localstring (after setting `stringTwo`) = 2
string two retain count = 2

And all of those values are precisely as one would expect.

  • When you first create the object referenced by the local variable, that object has a +1 retain count.

  • When you set the retain property, stringOne , the object's retain count will be incremented to +2 , and as both localstring and stringOne reference that same object, they'll both report the same retainCount .

  • But when you use the assign property, stringTwo , though, the retainCount does not change.

When you declare a property with retain , it automatically 'retains' the object, thus increasing its retain count.

So NSMutableString *localstring= [[NSMutableString alloc] initWithString:@"test"]; makes retain count = 1;

Then self.stringOne = localstring; makes retain count = 2.

My thinking is if the property is given retain, then after this line self.stringOne = localstring , the retain count of self.stringone should become one

When you create an object, it will start with a retain count of 1.

First of all, never use retainCount for anything. It is simply not reliable since it is a global retain count, and can be influenced by other factors outside of your code. Amazingly, in this case, it is correct though. Let's examine:

//Immediately localstring is +1 because you allocated it
NSMutableString *localstring= [[NSMutableString alloc] initWithString:@"test"];

//self.stringOne is a retain property, so localstring is incremented again (+2)
self.stringOne = localstring;

//self.stringTwo is a retain property, so localstring is incremented again (+3)
self.stringTwo = localstring;


Note that now localstring , self.stringOne and self.stringTwo all point to the same location in memory. You are not copying the memory contents every time you use the = sign (your way of thinking seems to indicate that you think that is how it works). You are simply pointing another variable at a location in memory and saying "Don't deallocate this piece of memory until I say so." (at least in the case of retain properties).

Conclusion: localstring's retain count, self.stringOne's retain count, and self.stringTwo's retain count are all the same.

Sidenote: It is impossible for an object to have a retain count of zero. The only time that can happen is when retainCount is sent to nil (which I assume self.stringOne is when you test it)

While it is never a good idea to look at retainCount when writing code, it is behaving as it should in this case. I think your understanding of memory management seems to be a little bit off.

To answer your question,

NSMutableString *localstring= [[NSMutableString alloc] initWithString:@"test"];

This creates a mutable string Object ,increments its retain count and returns a pointer to it. Note that retainCount is associated with the Object and not the pointer.

When you assign it to your retain property,

self.stringOne = localstring;

it passes retain to your Object and increments its retain count by 1 again. Now your object's retain count is 2 and both the pointers point to the same object. So, when you log retainCount , you get what you get. Hope this answers your question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM