我是否必须复制并自动发布此字符串?

时间:2009-09-04 08:56:39

标签: iphone cocoa cocoa-touch uikit

通过此步进调试器时,dfString在[df release]

之后无效
- (NSString*)dateFormatStringWithLocale:(NSLocale*)locale {
    NSDateFormatter* df = [[NSDateFormatter alloc] init];
    [df setDateStyle:NSDateFormatterShortStyle];
    [df setTimeStyle:NSDateFormatterShortStyle];
    [df setLocale:locale];
    NSString *dfString = [df dateFormat]; // dfString now contains nice date format
    [df release]; // seems to also kill dfString ???
    return dfString; // dfString is invalid here
}

让我们考虑一下:dfString是一个对象,就像任何其他对象一样。我用[df dateFormat]从df索取一个字符串。不过,我没有这个字符串,所以我不必释放它。但我拥有df,所以我发布它。现在让我们假设我从[df dateFormat]获得的字符串是df的一些ivar,并且在df的-dealloc中得到-release。那该死的字符串消失了。但是当我在那个dfString上调用-retain时,它只是指向df所拥有的字符串的指针,那么该死的df将不会被释放。那么,我该怎么办?复制字符串并自动释放它?

5 个答案:

答案 0 :(得分:2)

我按照你的说法做一个自动释放的字符串,如下所示:

NSString *dfString = [NSString stringWithString: [df dateFormat]];

或者那样:

NSString *dfString = [[[df dateFormat] copy] autorelease];

我更喜欢第一个,但如果有任何问题,请纠正我。

答案 1 :(得分:1)

将NSDateformatter设置为autorelease:

NSDateFormatter *df = [[[NSDateFormatter alloc] init] autorelease];

然后删除版本

[df release];  //  Remove this line

这样你就会返回一个完全自动释放的对象,就像obj-c中的实例方法中的约定一样

答案 2 :(得分:1)

这是一个所有权问题。格式化程序拥有您正在查看的字符串。因此,一旦格式化器消失,字符串就会死掉。你应该以某种方式使用copy或retain来声明该字符串的所有权。

这实际上取决于访问者方法的实现方式。以下两种实现都是完全有效的:

- (NSString*) dateFormat
{
    return dateFormat;
}


- (NSString*) dateFormat
{
    return [[dateFormat copy] autorelease];
}

实际上第一个只适用于你可以确定dateFormat是一个不可变的NSString。即如果你创建了一个你交给的任何字符串的副本。否则,调用者可能会想要更改您拥有的字符串。

答案 3 :(得分:0)

我认为您对它应该如何工作的理解是正确的(至少通过检查)您的代码也是正确的。

我的猜测是调试器没有说明全部真相,可能与编译器优化级别或类似情况有关。

答案 4 :(得分:0)

试试这个:

NSString *dfString = [[df dateFormat] retain];

由于dfString可能是dfString的实例变量,因此在释放df时它会被释放。尝试保留dfString。在dealloc中,其retainCount下降了一个,但由于您现在拥有所有权,因此不会完全释放。看看是否有帮助。