1. NSString *str1 = [NSString stringWithInt: 10];
2. NSString *str2 = [[NSString alloc] initWithInt: 10];
What is the difference between these methods?
CodePudding user response:
The history goes to times when automatic reference counting doesn't existed.
Then Apple have created notation, that methods with prefixes init
, copy
, new
returns owned pointer, that mean that you don't need to retain
it, other methods should return autoreleased pointers. For example
NSString *a;
NSString *b;
@autoreleasepool {
a = [[NSString alloc] initWithFormat:@"%d", 1];
b = [NSString stringWithFormat:@"%d", 2];
NSLog(@"String a in autorelease pool is %@", a); //output: String a in autoreleasepool is 1
NSLog(@"String b in autorelease pool is %@", b); //output: String b in autoreleasepool is 2
}
NSLog(@"String a out of autorelease pool is %@", a); //output: String a out of autorelease pool is 1
NSLog(@"String b in autorelease pool is %@", b); //crash: referencing invalid object, because b was autoreleased but variable `b` still pointing at released object
For proper working outside autoreleasepool variable b
should be retained:
NSString *b;
@autoreleasepool {
b = [[NSString stringWithFormat:@"%d", 2] retain];
NSLog(@"String b in autorelease pool is %@", b); //output: String b in autoreleasepool is 2
}
NSLog(@"String b out of autorelease pool is %@", b); //output: String b out of autorelease pool is 1
But if you use retain
properties, you will face opposite situation: memory leaks.
Proper code will be
@property (retain) NSString *a;
@property (retain) NSString *b;
@autoreleaspool {
self.a = [[[NSString alloc] initWithFormat:@"%d", 1] autorelease];
self.b = [NSString stringWithFormat:@"%d", 2];
}
So exact implementation of stringWithFormat:
is doing alloc
init
autorelease
Of course now when we have ARC
we don't need think about proper object retaining and releasing.
In ARC
first code snipped will work fine without crashes, second code snippet will work fine without memory-leaks.
So now it's just for programmer sense which one he prefer most. It's like in swift: you can write: SomeClass(...)
or SomeClass.init(...)
CodePudding user response:
The first is a class factory method. See http://www.apeth.com/iOSBook/ch04.html#_class_methods_2
The second is a genuine initializer.
The difference between them was much more obvious back in the day of manual memory management. Now that ARC exists, they are indistinguishable — which is why Swift eliminates the former.