views:

94

answers:

4

Hi all i'm still new to iPhone development, but had strong experience with other programming languages. The thing that makes me pull my hair out is the Obj-C memmory management and releasing / retaining properly. I know the concept, i know "once i understand it will be easy" but i'm not quite still there, and that makes me crazy. Here i have one simple piece of code with class and method, that simply add's one character to existing string that is synthesized so used as class proprety ... the class for example is called myClass ...

myClas.h

@interface myClass : NSObject {
  @private 
  NSString* someCommonString;
}
@propery (retain, nonatomic) NSString* someCommonString;

myClass.m

...

@synthesize someCommonString;    

- (id) init 
{
   self = [super init];

   if(self)
   {
       someCommonString = [[NSString alloc] initWith String:@"one "];
   }
}

- (NSString*) appendString:(NSString*) stringToAdd
{
    NSString* result = [someCommonString stringByAppendingString: stringToAdd];
    return result;
}

- (void) doTheJob 
{
   NSString* test1 = @"two ";
   NSString* test2 = [[NSString alloc] initWithString: @"three "];
   NSString* test3 = [NSString stringWithFormat:@"four "];

   self.someCommonString = [self appendString:test1];
   self.someCommonString = [self appendString:test2];
   self.someCommonString = [self appendString:test3];

   NSLog(@"%@", someCommonString); 
}

- (void) dealloc
{
   [someCommonString release];
   [super release];
}
...

Ok, after i alloc myClass and execute the doTheJob method, i should have @"one two three four" in the someCommonString class proprety. I know this is working, but is also leaking as hell. test1, test2 and test3 are 3 ways of initialising NSString, and only the test2 should be released, this is quite self-explanatory, but im much more worried what happens when passing them as arguments to the appendString method. Because there i know i hawe a leak, but don't know how to handle 1. stringToAdd argument [should i worry about it in appendString method at all ?] 2. the result -> if i autorelease the result, i don't know at which point the result will be deallocated. 3. sommeCommonString in appendStringMethod, should i retain it, release it or leave it alone ?

Huh :)

+1  A: 

Hello there!

At a first glance, it seems to me like you're not releasing test2. After you have appended it to your common string, you do not need to retain it anymore.

self.someCommonString = [self appendString:test1];
self.someCommonString = [self appendString:test2];
self.someCommonString = [self appendString:test3];
[test2 release];

The other two (test1 and test3) are autoreleased, so your thread will reclaim them at some point).

As far as your appendString: method is concerned, result is already autoreleased and in fact you could reduce your implementation to

return [someCommonString stringByAppendingString: stringToAdd];

someCommonString is not affected by the operation at all. stringByAppendingString: returns a new autoreleased string from the concatenation of self and stringToAdd.

Hope that helps

fedmest
Thank you very much! Though that stringByAppendingString was not autoreleased
A: 

… but im much more worried what happens when passing them as arguments to the appendString method. Because there i know i hawe a leak, but don't know how to handle
1. stringToAdd argument [should i worry about it in appendString method at all ?] …

You don't have a leak in -appendString:. You are passing stringToAdd around without retaining it and that's okay here. The result is autoreleased and you don't have to take any action on it.

2. the result -> if i autorelease the result, i don't know at which point the result will be deallocated.

The result is already autoreleased and will be released as soon as the current NSAutoreleasePool will be released. Til then you can pass it around without retaining.

3. sommeCommonString in appendStringMethod, should i retain it, release it or leave it alone ?

Leave it alone, it's managed by the accessors. But as fedmest (and you too) said: release test2.

Tilo Prütz
A: 

Well there are few problems in your code, but basic problem is you need NSMutableString string, not NSString to make your code work.

  1. in init method, correct code to initialize is,

    someCommonString = [[NSMutableString alloc] initWithString:@"one "];

  2. You have to return the object (self) from init, otherwise it will not work, like this.

    return self;

  3. If you wanted to append the string, it should be NSMutableString, not NSString.

    [[self someCommonString] appendString:test1];

    [[self someCommonString] appendString:test2];

    [[self someCommonString] appendString:test3];

  4. In dealloc method, you call dealloc method of super, not release the super. So correct it it like this.

    [super dealloc];

  5. There is no need to release test1 and test3, because they are autorelease.

I have witten the correct code, try this out.

@interface myClass : NSObject {
@private 
    NSMutableString* someCommonString;
}
@property (retain, nonatomic) NSMutableString* someCommonString;

- (void) doTheJob;
@end


@implementation myClass
@synthesize someCommonString;


- (id) init 
{
    self = [super init];

    if(self)
    {
        someCommonString = [[NSMutableString alloc] initWithString:@"one "];
    }

    return self;
}

- (NSString*) appendString:(NSString*) stringToAdd
{
    NSString* result = [someCommonString stringByAppendingString: stringToAdd];
    return result;
}

- (void) doTheJob 
{
    NSString* test1 = @"two ";
    NSString* test2 = [[NSString alloc] initWithString: @"three "];
    NSString* test3 = [NSString stringWithFormat:@"four "];

    [[self someCommonString] appendString:test1];
    [[self someCommonString] appendString:test2];
    [[self someCommonString] appendString:test3];



    NSLog(@"%@", someCommonString); 

    [test2 release];
}

- (void) dealloc
{
    [someCommonString release];
    [super dealloc];
}
@end
itsaboutcode
Thank you much for your effort. Sorry i maded few typos, and forgot to retype the return ... A bit worried about your redou, with [[self someCommonString] appendString ... you are calling a method appendAstring on someCommonString that generates urecognised selector. 4 me this would work only if used with categories with NSString/NSMutableString ? I used stringByAppendingString on regullar NSString without trouble, but not sure if this is correct ?
stringByAppendingString will only concatenate the string with your string object and return appended string, but it will not change your original string content.
itsaboutcode
A: 

This is a technique which might help you deal better with what is happening with the @synthesize directive. Change your header as follows

@interface myClass : NSObject {
   @private 
   NSString* _bob;
}
@propery (retain, nonatomic) NSString* someCommonString;

and your class file to

@synthesize someCommonString = _bob;  

If you recompile your code you will get build errors. Fix these and you will suddenly be able to see exactly what you are accessing via the synthesized property and what you are directly accessing.

Additionally, as already mentioned, you need to release test2 in the doTheJob method.

toxaq
You catched also my doubt that was hidden between the lines! Will try this for sure!, thank you very much!