I thought these two methods were (memory allocation-wise) equivalent, however, I was seeing “out of scope” and “NSCFString” in the debugger if I used what I thought was the convenient method (commented out below) and when I switched to the more explicit method my code stopped crashing! Notice that I am getting the string that is being stored in my container from sqlite3 query.
p = (char*) sqlite3_column_text (queryStmt, 1);
// GUID = (NSString*) [NSString stringWithUTF8String: (p!=NULL) ? p : ""];
GUID = [[NSString alloc] initWithCString:(p!=NULL) ? p : "" encoding:NSUTF8StringEncoding];
Also note, that if I looked at the values in the debugger and printed them with NSLog they looked correct, however, I don’t think new memory was allocated and the value copied. Instead the memory pointer was stored – went out of scope – referenced later – crash!
If you need to keep a reference to an object around after a method returns, then you need to take ownership of the object. So, if your variable
GUIDis an instance variable or some kind of global, you will need to take ownership of the object. If you use the alloc/init method, you have ownership of the object returned since you usedalloc. You could just as easily use thestringWithUTF8String:method, but you will need to take ownership explicitly by sending aretainmessage. So, assumingGUIDis some kind of non-method-scoped variable:(either
copyorretaincan be used here to take ownership, butcopyis more common when dealing with strings).Also, your code may be a little easier to read if you did something like: