stringWithFormat 和 initWithFormat 有何不同?
+ stringWithFormat:
– initWithFormat:
一个类方法,一个实例方法 都是格式化字符串
1、 initWithFormat是实例方法
只能通过 NSString* str = [[NSString alloc] initWithFormat:@”%@”,@”Hello World”] 调用,但是必须手动release来释放内存资源(非ARC环境)
2、 stringWithFormat是类方法
可以直接用 NSString* str = [NSString stringWithFormat:@"%@",@"Hello World"] 调用,内存管理上是autorelease的,不用手动显式release
一个常见错误:(非ARC环境)
label.text = [[NSString alloc] initWithFormat:@”%@”,@”abc”];
最后在dealloc中将label给release掉
但是仍然会发生内存泄漏!
原因在于:用label.text = …时,实际是隐式调用的label的setText方法,这会retain label内部的字符串变量text(哪怕这个字符串的内容 跟传进来的字符串内容相同 ,但系统仍然当成二个不同 的字符串对象),所以最后release label时,实际上只释放了label内部的text字符串,但是最初用initWithFormat生成的字符串并未释放,最终造成了泄漏。
解决办法有二个:
1、
NSString * str = [[NSString alloc] initWithFormat:@”%@”,@”abc”];
label.text = str;
[str release]
最后在dealloc中再[label release]
2、
label.text = [NSString stringWithFormat:@"%@",@"abc"];
然后剩下的事情交给NSAutoreleasePool
例如:
非ARC环境下,循环构造10w个NSString,内容一样:
首先是stringWithFormat,占用内存 5.2M
for (int i = 0; i < 100000; i++) {
[NSString stringWithFormat:@"%d",1234567890];
}
然后加上@autoreleasepool,占用内存 520KB
for (int i = 0; i < 100000; i++) {
@autoreleasepool {
[NSString stringWithFormat:@"%d",1234567890];
}
}
再来试试initWithFormat,占用内存 3.6MB
for (int i = 0; i < 100000; i++) {
[[NSString alloc] initWithFormat:@"%d",1234567890];
}
再加上autorelease尾巴和autoreleasepool,占用内存 520KB
for (int i = 0; i < 100000; i++) {
@autoreleasepool {
[[[NSString alloc] initWithFormat:@"%d",1234567890] autorelease];
}
}
+ stringWithFormat:
类方法,返回一个autorelease的NSString实例,不用手动Release,在自动释放池中会自动释放。
– initWithFormat:
实例方法,返回一个自己Alloc申请内存的NSString实例,根据OC内存管理黄金法则,管杀管埋,它则需要自己手动Release。
两个方法只是在没有使用ARC的时候有所不同,一个需要手动Release一个则是自动进入autoreleasepool,所以在使用ARC的时候他们俩几乎没有什么区别。