Thanks to everyone for the answers. These answers helped, albeit in few places, I had to figure out the rest myself. I focused a lot more on this idea rather than a linear implementation, but it was hard to describe it here without inserting huge chunks of code. It's just that this delegate for parsing XML objects is a very specific example, since it does not return a value as such, the value must be accepted and assigned from the outside.
I note that Adam answers as the best, as the most detailed, although not answering all my problems.
For others - http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html is a great read. Also read my own answers to questions:
1 - Of course, I should not let go of this object. A memory leak was not caused by this.
2 - this method is nothing special, it just returns a simple auto-implemented object, as others tried to explain to me here. The root of my initial problems was that I didn’t have this before, but soon called [model release], as a result of which the autoplay pool sent the release to a non-existent object. I should not do [model release] because I do not own this object. In fact, this retention is not even required here, because I just need an object to get value from it, and then I can break it, so it can be safely transferred to the autorun pool without saving.
3 - I intended this method (loadData) to be independent, so I did not set any instance variables, but returned an array for others. This was a parallel example, it is not that I have two variables with the same name in the method.
If I declare an object in this method (situation No. 2), it just happens that it is automatically solved at the end of this method, because after its completion the control returns to the application and deletes the pool. ok with me in this example because later I don't need an array. In the real world, probably I should have an instance variable (situation # 1), and then go with self.objectArray = [self loadData], because it will run setter, and the object with auto-implementation will be saved for me.
4 - I was a little confused here. Basically I tried to code in objecive-c with manual memory management, but still had a garbage collector related. It is very important to remember that if you execute [[object alloc] init], and then later [release the object] - it should not automatically be that the object is destroyed! The release is not nullifying! This, of course, is a fundamental rule (preservation / liberation), but even knowing it is easy to forget. Keep track of what you are doing with your object between these two lines - the object can actually live for a long time, because "someone" will still become its owner. The release method at the end of the life cycle of this class does not mean that the object is now destroyed, but means: "I no longer care, my hands are clean"
So line by line:
objectArray = [[parserDelegate objectArray] copy];
This is beautiful, I do not copy deeply. I am copying an array, which means that it allocates new memory for the array object, but not for the content. BUT, the copy sent to objectArray also sends a save to each object. In my example, I release my parserDelegate, which also releases its own Array object, decreasing saveCount for each object. If I had not made a copy here, the objects reached keepCount = 0 and would be destroyed. Thus, I have a new array with pointers to old objects, but they essentially become my objects, because the previous array is destroyed, and because of my save, I become the owner. Sorry if this says too much, but I really needed to focus in order to figure it out.
else if ([elementName isEqualToString:@"name"]) { // do i have to init currentObject.name (NSString) here? i guess not? [self setParseChars:YES]; // just set the flag to make parse control easier }
The question here was whether I should initialize the currentObject.name NSString property, because it will be filled shortly after the characters are found. Now it is interesting. When you initialize the entire object, its NSString properties are zero. Now, later, I do
currentObject.name = currentChars;
What launches the setter. This setter is defined as (non-atomic, persistent), which means that the new value is saved, the old value is freed and a pointer is assigned. It's funny, no matter if the previous value is initialized or not - if it is initialized, it will be released anyway, if it is zero, then nil can still accept the release (although I'm not 100% sure?) - nothing will happen. But, for the sake of correctness, I assume that the initial line should look like this:
else if ([elementName isEqualToString:@"name"]) { currentObject.name = [NSString new]; // just alloc/init routine [self setParseChars:YES]; // just set the flag to make parse control easier }
Now:
[currentChars autorelease];
Must not be. This is a confusing design, and it was a bad decision. All that should be there is just an init string.
[objectArray addObject:[currentObject copy]];
There is no need for copying. addObject will persist anyway. It makes no sense to create another distribution. That was my cause of my leaks.
Everything else is fine. Since I release currentChars right after setting the value for my object, it now saves it and becomes the owner, and I just release it “here” in the parser because I no longer need it (this will be highlighted in the next loop).
This can be confusing, but I can imagine that there will be other problems with non-standard memory, and even for experienced people, it may be a problem to put things in the right places. Maybe my story will help then.