我知道任何初始化...方法初始化一个新对象,然后NSString stringWithString将参数字符串复制为新对象。我也明白,作为对象的所有者,我可以控制我分配的任何对象的释放/释放。我不明白的是,我什么时候应该使用stringWithString方法,因为以这种方式分配的任何局部变量都将由NSString而不是局部类“拥有”它的内存。
Kochan的“Objective C中的编程”一书(第1版)使用以下代码(参见第342-344页)来解释initWithString比stringWithString更可取,因为AddressCard类将拥有名称变量内容。而且,在使用stringWithString方法重复调用setName版本时,我没有收到任何错误。蒂娅!!
//header file has appropriate declarations but not included here:
#import "AddressCard.h"
@implementation AddressCard;
-(NSString *) name
{
return name;
}
//Recommended code:
-(void) setName: (NSString *) theName
{
[name release]
name = [[NSString alloc] initWthString: theName];
}
//Incorrect code according to Kochan:
-(void) setName: (NSString *) theName
{
[name release]
name = [NSString stringWthString: theName];
}
//rest of class implementation code snipped
@end发布于 2008-11-25 20:20:19
我不明白的是,我什么时候应该使用stringWithString方法,因为以这种方式分配的任何局部变量都会被NSString而不是局部类“拥有”它的内存。
什么?不是的。
规则很简单:
当接收对象的保留计数为1.
retain时,alloc、copy、copyWithZone或new返回的任何对象的保留计数都会增加,接收对象的保留计数会减少,接收对象的保留计数会告诉当前的自动释放池“稍后”向接收对象发送release消息。
release”的工厂方法(例如,stringWithString:)返回代表您自动释放的对象。或者,稍微消化一下:
copy、alloc、retain或new的任何方法都会返回您拥有的对象。您显示的不正确的setName:实现是不正确的,因为当您打算拥有对象时,它会将自动释放的对象存储在实例变量中。您应该保留它,或者,在这种情况下,复制它。一种方法是简单地使用alloc和initWithString:,如您所示的正确示例;另一种方法是copy。
The Memory Management Programming Guide for Cocoa explains everything.每个Cocoa或Cocoa Touch程序员都应该不时地阅读或重新阅读它。
发布于 2008-11-25 20:45:05
实际上,两个setter都是错误的。由于一般的内存管理原因,“不正确”的那个是错误的(这在其他地方有很好的阐述)。“推荐的”是错误的,原因有两个:
“正确”(IMHO)方法是:
-(void) setName: (NSString *) theName
{
if (theName == name) return; // if they're equal, no need to do anything further
[name release];
name = [theName copy]; // sets name to nil if theName is nil
}对于大多数对象,您实际上希望在第三行使用-retain而不是-copy,但是对于字符串,复制几乎总是更好。
发布于 2008-11-25 20:05:28
initWithString和stringWithString之间的区别在于stringWithString返回一个自动释放的指针。这意味着你不需要专门释放它,因为下次自动释放池清理任何自动释放的指针时,它将被处理。
另一方面,initWithString返回一个保留计数为1的指针-您确实需要在该指针上调用release,否则将导致内存泄漏。
查看https://stackoverflow.com/questions/193288/what-is-the-cost-of-using-autorelease-in-cocoa,了解一些原因,比如为什么应该使用自动发布vs release。
https://stackoverflow.com/questions/318666
复制相似问题