I am currently trying to work myself into iOS development. Right now I’m having trouble understanding memory management.
This is the cause of my confusion:
NSString *path = [self.dataPath stringByAppendingPathComponent:@"dummy.plist"];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
NSString *dummyKeyValue = [dict valueForKey:@"dummyKey"];
// NSLog(@"%@",[NSString stringWithString:dummyKeyValue]);
[dict release];
NSString *anotherString = [dummyKeyValue lowercaseString];
This piece of code triggers an EXC_BAD_ACCESS error on the last line. Seemingly because NSDictionary releases its key values. What I don’t understand is why the dummyKeyValue definition is not being taken into account, because obviously dummyKeyValue is still pointing to the value of "dummyKey".
Now the next problem and even funnier phenomenon occurs when you comment out the NSLog line. Using dummyKeyValue in one way or another seems to prevent the release of the memory it points to. WHY?
Help is appreciated!
In manual reference counting mode, simply defining a variable doesn’t mean that the object the variable points to will automatically be kept around. When
dictis released, it releases its value objects, and if there are no other objects with a strong reference to them (i.e. their reference count is now 0), they are released. That’s what you appear to be seeing here.If you want to keep a strong reference to dummyKeyValue, you need to retain it after receiving it. Of course, that also means you need to release it when you’re done with it. Try this:
Now dummyKeyValue will stick around until the end of the current autorelease pool scope. Often, accessor methods are written to do just this before returning a value to avoid exactly the situation you’re seeing.
Worth noting is that if you were using ARC (Automatic Reference Counting), you wouldn’t have this problem as the compiler would insert the necessary retain/release calls to ensure that dummyKeyValue stuck around until you were done with it.