我知道任何init ...方法都会初始化一个新对象,并且NSString stringWithString会将参数字符串的副本作为新对象.我也理解作为对象的所有者,我可以控制我分配的任何对象的释放/释放.我不明白的是什么时候我会使用stringWithString方法,因为任何以这种方式分配的局部变量都会让它的内存由NSString而不是本地类"拥有".
Kochan的"Objective in Objective C"一书(第1版)使用以下代码(参见第342-344页)来解释initWithString比stringWithString更可取,因为AddressCard类将拥有名称变量contents.另外,使用stringWithString方法重复调用setName版本时,我没有任何错误.TIA!
//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
Peter Hosey.. 27
我不明白的是什么时候我会使用stringWithString方法,因为任何以这种方式分配的局部变量都会让它的内存由NSString而不是本地类"拥有".
什么?没有.
规则很简单:
任何对象返回的alloc
,copy
,copyWithZone
,或new
具有为1的保留计数.
retain
增加接收对象的保留计数.
release
减少接收对象的保留计数.
autorelease
告诉当前自动释放池向接收对象发送release
消息"稍后".
名称中没有"new"或"copy"的任何工厂方法(例如stringWithString:
)返回一个代表您自动释放的对象.
或者,消化了一下:
任何方法的名称包含copy
,alloc
,retain
,或new
返回你自己的对象.
任何没有的方法都会返回一个你不拥有的对象.
拥有一个对象,保留它.
setName:
您显示的错误实现是不正确的,因为它将一个自动释放的对象存储在实例变量中,当您意味着拥有该对象时.你应该保留它,或者在这种情况下,复制它.一种方法是简单地使用,alloc
并且initWithString:
如您所示的正确示例; 另一种方式copy
.
Cocoa的内存管理编程指南解释了一切.每个Cocoa或Cocoa Touch程序员都应该不时阅读或重新阅读.
我不明白的是什么时候我会使用stringWithString方法,因为任何以这种方式分配的局部变量都会让它的内存由NSString而不是本地类"拥有".
什么?没有.
规则很简单:
任何对象返回的alloc
,copy
,copyWithZone
,或new
具有为1的保留计数.
retain
增加接收对象的保留计数.
release
减少接收对象的保留计数.
autorelease
告诉当前自动释放池向接收对象发送release
消息"稍后".
名称中没有"new"或"copy"的任何工厂方法(例如stringWithString:
)返回一个代表您自动释放的对象.
或者,消化了一下:
任何方法的名称包含copy
,alloc
,retain
,或new
返回你自己的对象.
任何没有的方法都会返回一个你不拥有的对象.
拥有一个对象,保留它.
setName:
您显示的错误实现是不正确的,因为它将一个自动释放的对象存储在实例变量中,当您意味着拥有该对象时.你应该保留它,或者在这种情况下,复制它.一种方法是简单地使用,alloc
并且initWithString:
如您所示的正确示例; 另一种方式copy
.
Cocoa的内存管理编程指南解释了一切.每个Cocoa或Cocoa Touch程序员都应该不时阅读或重新阅读.
实际上,两个人都错了.由于一般的内存管理原因(其他地方已经很好地阐述),"错误的"错误."推荐"的错误有两个原因:
if(theName == name),那么你可能会在第一行释放你的对象,然后尝试在第二行使用deallocated对象作为-initWithString:的参数,导致未定义的行为.
-initWithString:不处理优雅地传递nil.
'正确'(恕我直言)方法是:
-(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 }
对于大多数对象,你实际上想要在第三行上获得而不是-copy,但对于字符串来说,复制几乎总是更好.