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.
Related
I have an NSTimer that fires once per second.
And every second I have an NSString that needs to be changed.
I've never tried to deal with memory management before so I'm not sure if what I'm doing is right but instruments is saying under "alloc" that the line of code with stringByReplacingOccurrencesOfString has 45MB of "Live Bytes" after about a minute...
(and the live byte count keeps on rising with every second and eventually crashes the app).
I think my issue lies somewhere with the MutableCopy code?
Here is my code:
-(void)myTimer {
if (testedit) {
[testedit release];
[withString1a release];
[forString1a release];
}
testedit = [[NSString alloc] init];
withString1a = [[NSString alloc] init];
forString1a = [[NSString alloc] init];
testedit = [[NSString alloc] initWithFormat:#"example"];
withString1a = [[NSString alloc] initWithFormat:#"e"];//this string gets its values randomly from an array in my real code
forString1a = [[NSString alloc] initWithFormat:#"flk34j"];//this string gets its values randomly from an array in my real code
testedit = [[testedit stringByReplacingOccurrencesOfString:withString1a withString:forString1a] mutableCopy];//memory leak /:
}
You are allocating memory for each object twice. When you alloc the second time and assign it to the same variable, the first piece of alloc'd memory becomes inaccessible and unreleasable.
Then you make a mutableCopy of testedit and assign the copy to the original's variable. Again, you leave a piece of inaccessible memory floating around.
The rule with non-ARC memory management is - for every alloc, new, copy or retain you need to have a corresponding release. You have 6 allocs, one copy, and only 3 releases.
Here are some suggestions.
Remove these duplicated allocations:
testedit = [[NSString alloc] init];
withString1a = [[NSString alloc] init];
forString1a = [[NSString alloc] init];
Presumably testedit, withString1a and forString1a are all iVars. (Please declare your iVars as autosynthesized properties and refer to them as self.testedit ... etc. that will make your code so much clearer to stack overflowers).
Take out all of this:
if (testedit) {
[testedit release];
[withString1a release];
[forString1a release];
}
Assuming these are all iVars, the correct place to release them is in your object's dealloc method
In fact withString1a and forString1a can be local variables, as you get their content from elsewhere:
NSString* withString1a = [[[NSString alloc] initWithFormat:#"e"] autorelease];
NSString* forString1a = [[[NSString alloc] initWithFormat:#"flk34j"] autorelease];
You can autorelease them as you don't need them to hang around after the method has finished.
These lines can also be written:
NSString* withString1a = [NSString stringWithFormat:#"e"];
NSString* forString1a = [NSString stringWithFormat:#"flk34j"];
(-stringWithFormat is a convenience method that returns an autoreleased object)
That leaves us with these two lines.
testedit = [[NSString alloc] initWithFormat:#"example"];
testedit = [[testedit stringByReplacingOccurrencesOfString:withString1a
withString:forString1a] mutableCopy];
It's not clear why you are treating testedit as an immutable string in the first line and a mutable string in the second. You don't need a mutable string here at all, as you are replacing testedit with a new string.
self.testedit = [[NSString alloc] initWithFormat:#"example"];
self.testedit = [[testedit stringByReplacingOccurrencesOfString:withString1a
withString:forString1a] copy];
(you need copy as stringByReplacingOccurrencesOfString:withString: returns an autoreleased object, and here you want to keep hold of it)
THE last piece of the jigsaw is getting rid of your _testedit iVar memory allocation. You do this in the dealloc method of your object:
- (void) dealloc {
[_testEdit release];
[super dealloc];
}
(Note that init, accessor, and dealloc methods are the three places where you should not refer to an iVar using property syntax.)
All good, but really, you should be using ARC! You are _far_more likely to introduce memory bugs this way than if you rely on the compiler to manage memory for you.
I would suggest you to make use of #property here.
In .h file declare the properties as:
#property (nonatomic, retain) NSString *testedit;
#property (nonatomic, retain) NSString *withString1a;
#property (nonatomic, retain) NSString *forString1a; //if required write the #synthesize as well in .m class
You can write your timer method as:
-(void)myTimer {
self.testedit = #"example";
self.withString1a = #"e";//this string gets its values randomly from an array in my real code
self.forString1a = #"flk34j";//this string gets its values randomly from an array in my real code
self.testedit = [self.testedit stringByReplacingOccurrencesOfString:self.withString1a withString:self.forString1a];
}
In dealloc method, you can set all the above properties as nil (self.testedit = nil;) or do a release on them([testedit release];).
If possible, try to switch to ARC, you dont have to worry about the memory management. The problem with your code was that you are using a lot of alloc/init statements without releasing the variable before doing it. This causes it to lose the reference of that variable and you will leak it. You dont need that many allocation statements. For every allocation or retain, there should be a corresponding release/auto-release statement.
If you're using ARC you shouldn't have an issue. If you aren't using ARC you can try adding autorelease:
testedit = [[[testedit stringByReplacingOccurrencesOfString:withString1a withString:forString1a] mutableCopy] autorelease];
You are getting a memory leak because you never de-allocate testedit. Whenever you call alloc, that means you need to deallocate it. This usually just means calling release.
Do something like this instead, then be sure to free up the memory you've allocated:
NSString* newString = [[testedit stringByReplacingOccurrencesOfString:withString1a withString:forString1a] mutableCopy];
I realize this question may sound dumb, but just bear with me. I built an app to help new developers wrap their head around memory retention on the iPhone (no ARC yet). It is plain and simple, 4 buttons, init, access, retain, and release. Pretty self explanatory. I am displaying what the retain count for my string object that is the target of our poking and prodding. (Please no lectures on use of [myVar retainCount], I already know)
This stuff will never make it into actual apps, just toying with it for fun and hopefully help someone learn how memory works. My retain and release all work great. My question is that why does my retain count drop back to 1 if I call myString = [[NSMutableString alloc] init]; again. I can boost my retain count to 40, but after calling alloc/init I go back to zero. I am not leaking anywhere, just curious what happens to myString if/when alloc/init is called on it again.
My question is that why does my retain count drop back to 1 if I call
myString = [[NSMutableString alloc] init]; again?
Because you are failing to understand a very basic concept of Objective-C; myString is not an instance of an NSMutableString, but a reference to an instance. If you were to:
myString = [[NSMutableString alloc] init];
myString = [[NSMutableString alloc] init];
You now have two instances of NSMutableString, one leaked.
If you:
myString = [[NSMutableString alloc] init];
otherString = myString;
You now have a single instance of NSMutableString with two references.
In all three allocations, the NSMutableString instance will have a +1 retain count and, thus, you must balance each with a single release or you'll leak.
Treating retain counts as an absolute count is a path to madness. Or, at best, the scope of usefulness of the absolute retain count is so limited that learning about it is not applicable to real world iOS programming.
This bears repeating:
The retainCount of an object is tricky business.
If you were to continue down this path, you should be aware of the following details:
retainCount can never return 0
messaging a dangling pointer is not guaranteed to crash
retain count cannot be known once you have passed an object through any system API due to implementation details
any subclass of any system class may have an unknown retain count due to implementation details
retain count never reflects whether or not an object is autoreleased
autoreleases is effectively thread specific while the retain count is thread global
some classes are implemented with singletons some of the time (NSString, certain values of NSNumber)
the implementation details change from platform to platform and release to release
attempting to swizzle retain/release/autorelease won't work as some classes don't actually use those methods to maintain the retain count (implementation detail, changes per platform/release, etc..)
If you are going to teach retain/release, you should be treating the retain count as a delta and focus entirely on "If you increase the RC, you must decrease it".
when you call myString = [[NSMutableString alloc] init];, you're not "calling alloc/init on it again". You're not calling a method on the same instance you had. You're allocating and initializing a new instance, a completely different object from the one you had before.
And if you're doing that with a variable that had an object that you retained, then yes, you are leaking it.
Try this.
NSString *myString = [[NSMutableString alloc] init];
NSLog(#"%d", [myString retainCount]); // "1"
for (int i = 1; i < 40; i++)
[myString retain];
NSLog(#"%d", [myString retainCount]); // "40"
NSString *backup = myString;
myString = [[NSMutableString alloc] init];
NSLog(#"%d", [myString retainCount]); // "1"
NSLog(#"%d", [backup retainCount]); // "40"
You see, you have a different object with a new retain count. Your original object still exists and still has the same retain count. Assignment changes the object a variable refers to. A variable doesn't have a retain count, an object does.
myString = someOtherString;
NSLog(#"%d", [myString retainCount]); // who knows?
With retained property:
self.iString = backup;
NSLog(#"%d", [self.iString retainCount]); // "41" - 1 more because property retained
NSString *newString = [[NSMutableString alloc] init];
NSLog(#"%d", [newString retainCount]); // "1"
self.iString = newString;
// 1 for alloc 1 for retain (in real code you should release newString next)
NSLog(#"%d", [self.iString retainCount]); // "2"
NSLog(#"%d", [backup retainCount]); // "40" - self.iString released it
Which way is correct?
NSString *c = [[NSString alloc] init];
self.character = c;
[c release];
or
self.character = [[NSString alloc] init];
And why? Thanks.
It depends on how your property is declared. If you used
#property (nonatomic, retain) NSString *someString;
The setter will be created to retain someString, in which case the correct way is your first method. If you used:
#property (nonatomic, assign) NSString *someString;
Your second method will be correct, since it will just assign the pointer and not retain anything.
It depends on how you've defined your property.
If it's copy or retain, the synthesized setter (setCharacter: in your example) will take ownership of any objects you assign to the property. In this situation your first example is correct. The second would lead to a memory leak as you've claimed ownership of the NSString twice and you will (probably) only relinquish ownership once; thus the memory can never be reclaimed.
If it's assign on the other hand, the setter won't do anything special and your second example would be correct. The first would result in an EXC_BAD_ACCESS error if you tried to do anything with the NSString. I should note that you generally only use assign for primitive types and delegates.
I suggest you have a read over the Memory Management Programming Guide and the Declared Properties section of The Objective-C Programming Language guide.
The answer depends on your #property definition. Likely it's something like (retain) or (copy) for an NSString. In that case, assigning to self.character will increment the retain count. So the bottom:
self.character = [[NSString alloc] init];
You've set the retain count to 1 with the alloc and self.character will also retain it for a count of 2, so that'll leak. Should be
self.character = [[[NSString alloc] init] autorelease];
or the top version.
The answer to this now with iOS 5 is to use ARC.
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'd still like some correct answers for the following code. I have a series of examples that I'd love for someone(s) to clarify.
Setting a value for an instance variable:
Say I have an NSMutableArray variable. In my class, when I initialize it, do I need to call a retain on it?
Do I do
fooArray = [[[NSMutableArray alloc] init] retain];
or
fooArray = [[NSMutableArray alloc] init];
Does doing [[NSMutableArray alloc] init] already set the retain count to 1, so I wouldn't need to call retain on it? On the other hand, if I called a method that I know returns an autoreleased object, I would for sure have to call retain on it, right? Like so:
fooString = [[NSString stringWithFormat:#"%d items", someInt] retain];
Properties:
I ask about the retain because I'm a bit confused about how #property's automatic setter works.
If I had set fooArray to be a #property with retain set, Objective-C will automatically create the following setter, right?
- (void)setFooArray:(NSMutableArray *)anArray {
[fooArray release];
fooArray = [anArray retain];
}
So, if I had code like this: self.fooArray = [[NSMutableArray alloc] init]; (which I believe is valid code), Objective-C creates a setter method that calls retain on the value assigned to fooArray. In this case, will the retain count actually be 2?
Correct way of setting a value of a property:
I know there are questions on this and (possibly) debates, but which is the right way to set a #property?
This?
self.fooArray = [[NSMutableArray alloc] init];
Or this?
NSMutableArray *anArray = [[NSMutableArray alloc] init];
self.fooArray = anArray;
[anArray release];
I'd love to get some clarification on these examples. Thanks!
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. :)
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
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
I have a very clear question:
//.h file
#property (nonatomic, retain)NSMutableString * retainString;
#property (nonatomic, copy)NSMutableString * copyString;
//.m file
#synthesis retainString, copyString;
-(void)Process
{
NSMutableString *test = [[NSMutableString alloc]inti];//retain count should be 1
self.retainString = test;
self.copyString = test;
}
cond. 1-> // retain count of both should be 2. As they are pointing to the same memory location with retain count 2 so how may release should be written.
cond. 2-> // //retain count of test is 1 and copyString is 2. As both hold different memory location. but can we write [copyString release].
This setup actually does some very interesting things, and raises a couple good points about Objective-C memory management. Let's first reiterate the code:
// Testing.h
#interface Testing : NSObject {
NSMutableString *retainString;
NSMutableString *copyString;
}
#property(nonatomic,retain) NSMutableString *retainString;
#property(nonatomic,copy) NSMutableString *copyString;
// Testing.m
#implementation Testing
#synthesize retainString, copyString;
- (id)init {
if(self = [super init]) {
NSMutableString *test = [[NSMutableString alloc] init];
NSLog(#"test %d; retain %d; copy %d", [test retainCount], [retainString retainCount], [copyString retainCount]);
self.retainString = test;
NSLog(#"test %d; retain %d; copy %d", [test retainCount], [retainString retainCount], [copyString retainCount]);
self.copyString = test;
NSLog(#"test %d; retain %d; copy %d", [test retainCount], [retainString retainCount], [copyString retainCount]);
[self.copyString appendFormat:#"test"];
NSLog(#"test %d; retain %d; copy %d", [test retainCount], [retainString retainCount], [copyString retainCount]);
}
return self;
}
#end
This produces the log output:
2009-12-24 03:35:01.408 RetainCountTesting[1429:40b] test 1; retain 0; copy 0
2009-12-24 03:35:01.410 RetainCountTesting[1429:40b] test 2; retain 2; copy 0
2009-12-24 03:35:01.410 RetainCountTesting[1429:40b] test 2; retain 2; copy 2147483647
2009-12-24 03:35:01.413 RetainCountTesting[1429:40b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with appendFormat:'
So what's going on here? The first two calls are fairly straightforward:
The initial call to alloc/init creates a new NSMutableString object with retain count 1, as expected. We have one object with one retain on it.
The assignment to the retained property increments the retain count, as expected. We have one object with two retains on it.
Here's where it gets strange. The assignment to the copy property does indeed make a copy, but not in the way you'd expect. NSString and NSMutableString are part of what's called a class cluster - when you create or modify a string, it may or may not be an instance of the class you're expecting. The language may mutate it to some other representation behind the scenes.
In this particular case, when the copy is performed, apparently the language decides that the string (since it contains no information) is to be considered immutable, and makes it so. This is often seen when people do something like [[NSString alloc] initWithString:#"hello"] - it's a constant, static string, so no object need be allocated dynamically. Keeping it static helps the runtime perform better.
So now we have two objects: our original test object that was retained twice, and the new object that is static and therefore has a retain count of INT_MAX. Finally, since the new string is immutable, calling a mutator method on it kills the program.
As an aside, changing the original call from init to initWithString: does make the copy assignment perform (somewhat) as expected - you only get a retain count of 1 on the copied object, but you still can't mutate it. Again, this is probably due to some optimization magic inside the compiler that decided that string was static and saw no reason to make it mutable if it didn't have to.
To answer your final question: yes, you can call release on either of these objects. It just won't do much. At best, you'll have destroyed the copied object (since it had a retain count of 1); at worst, it'll do nothing to a static string object. However, I'd recommend continuing to work through properties: rather than releasing the copied object, why not just do self.copyString = nil;? Since it calls the property setter, it'll take care of the release as necessary, and then you don't have a pointer to the object still floating around.
For more information on all this, consider reading:
Memory Management Programming Guide for Cocoa
The NSString class reference
The Objective-C Programming Guide, Declared Properties section
If you have properties defined with keywords 'retain' or 'copy' you should always release corresponding member variables in the dealloc method.
In this case your dealloc should look like this:
- (void)dealloc {
[retainString release];
[copyString release];
[super dealloc];
}
Now, when you alloc a string in your custom class' method, this method owns the string as described in the Memory Management Programming Guide for Cocoa. This means that you should release the string before leaving the method.
#synthesize retainString, copyString;
- (void)Process {
NSMutableString *test = [[NSMutableString alloc] init]; //retain count is 1
self.retainString = test; // retain count of test is 2
self.copyString = test; // test's retain count = 2, copyString's = 1
[test release]; // retain count of test is 1 again
}
When an instance of this class is destroyed, the dealloc method will be invoked which will in turn release both strings. And as soon as their have retain counts remain 1, they will be dealloc'ed too.
This may also help
NSString property: copy or retain?