vnguyen vnguyen - 5 months ago 40
Objective-C Question

stringWithFormat and initWithFormat result different values in ARC

I am new to objective C and iOS. I am confused with 2 resulting values when using NSString stringWithFormat and initWithFormat like bellow:

NSString* str0 = @"Hello";
__weak NSString* str1 = [[NSString alloc] initWithFormat:@"%@", str0 ]; // warning: Assigning retained object to weak variable; object will be released after assignment
__weak NSString* str2 = [NSString stringWithFormat:@"%@",str0];

NSLog(@"Result: str0 %@, str1 %@, str2 %@", str0, str1, str2);


Output: Result: str0 Hello, str1 (null), str2 Hello

Looking around network, the answers for these callers are same under ARC example: stringWithFormat vs initWithFormat under ARC

However with above code, the str2 seems to not meaning regardless weak or strong here, i.e. I can remove __weak of str2 declaration and makes same result.

My concern is that, if the creation of string by stringWithFormat is owned by framework (or by some other way out of scope of user application)?

Answer

My answer to your question

If you want to have a weak attribute to a property someone should have already retained it

.h

@property (nonatomic, weak) NSString *str1;
@property (nonatomic, weak) NSString *str2;

.m

@synthesize str1,str2;


-(void)viewDidLoad
{
   NSString* str0 = @"Hello";
   NSString* str1 = [[NSString alloc] initWithFormat:@"%@", str0 ];
   NSString* str2 = [NSString stringWithFormat:@"%@",str0];
   NSLog(@"Result: str0 %@, str1 %@, str2 %@", str0, str1, str2);
}

Output

Result: str0 Hello, str1 Hello, str2 Hello

Graver answer here

Detailed Explanation from Apple Forum Document

The difference is in how the return values are memory-managed. alloc/initWithFormat: returns a retained string that you will have to release or autorelease yourself. stringWithFormat: returns a string that has already been autoreleased. (An autoreleased object will be released when the current autorelease pool disappears; that usually happens right before the next event is processed.)

Which you should use depends on what you're doing with the string. If it's a temporary string, if it's going to be stored inside another object, or if it's going to be stored in your own object using the "self.property" syntax, use stringWithFormat:; if it's going to be assigned to a global, static or instance variable (without using "self.property"), use alloc/initWithFormat:.

In your case, you could go either way. stringWithFormat: would allow you to remove the explicit release call, but autoreleasing is also very slightly slower than releasing. It's up to you to decide whether you want your code to be smaller and simpler or longer and faster.