初学者问题:
我正在尝试了解一些基本的内存管理。如果我重写了一个setter方法,下面是否能充分处理传入字符串的内存管理?
- (void)setMyString:(NSString *)string
{
if (_myString != string){
[string retain];
[_myString release];
_myString = string;
}
}
我的逻辑是,一旦我们进入if语句,我想获取传入字符串的所有权,因此保留。接下来我发布_myString对象。然后我将_myString对象设置为字符串对象。这是我困惑的根源:我是否需要保留myString对象?或者我是否因为将其设置为字符串对象而对其拥有所有权?
谢谢!
答案 0 :(得分:4)
你写的是正确的,除了最后的。return _myString
陈述
当您在字符串上调用retain时,您将该实例的引用计数递增1。将字符串的值指定为_myString
不会更改实际实例(现在string
和_myString
指向),因此不需要第二次保留,并且不正确。< / p>
所有这一切,你所得到的都是多余的。 if (_myString != string)
检查的原因是,如果使用您已有的同一对象调用setter,则不希望在有机会保留该对象之前释放该对象。程序将在这种情况下崩溃,因为你释放它,它被取消分配,但你保留对它的引用并继续使用它(发送消息)。由于对象是相同的,如果函数的参数与实例变量的当前值相同,则可以通过简单地不执行任何操作来避免此问题。但是,在释放实例变量之前保留参数是实现完全相同的另一种方法。
所以,你可以这样做:
- (void)setMyString:(NSString *)string
{
if (_myString != string) {
[_myString release];
_myString = [string retain];
}
}
或者这个:
- (void)setMyString:(NSString *)string
{
[string retain];
[_myString release];
_myString = string;
}
我倾向于支持第一种方法,因为如果值相同则(非常稍微)更快,并且在写出时更简单一些。但实际上,这取决于个人偏好,原始问题中的表格也很好。
答案 1 :(得分:1)
不要再使用保留和释放。只需使用ARC,它将为您节省很多麻烦。您不必处理内存泄漏,编写大量保留/释放等等。
它适用于iOS 4,而且由于目前的iOS版本为6,所以现在使用ARC比使用ARC新版本时更好。
答案 2 :(得分:0)
还有一点缩短形式:
- (void)setFoo:(NSString *)aFoo {
[_foo autorelease];
_foo = [aFoo copy];
}
此外,来自google objective-c styleguide的提示:
永远不要只保留字符串。这可以避免调用者在您不知情的情况下将其更改为您。不要假设因为你接受的NSString实际上并不是NSMutableString。