请在代码中查看我的评论:
-(id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t
{
[super init];
coordinate = c;
NSDate *today = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterLongStyle];
NSString* formattedDate = [NSString stringWithFormat:@"%@ %@",
[dateFormatter stringFromDate:today], t];
[self setTitle:formattedDate]; //Why does the app crash when I try and release formattedDate? I have after all passed its reference to the title property?
[dateFormatter release]; //I need to release the dateformatter because I have finished using it and I have not passed on a reference to it
return self;
}
答案 0 :(得分:6)
不,看起来不错。 stringWithFormat
返回一个自动释放的对象 - 除非你retain
它没有,否则你不拥有它,所以你不能释放它。您自己分配了dateFormatter
,因此 拥有它并且必须release
。
(参见object ownership documentation和8个非常相似的SO问题。这必须是在这里显着增加的头号目标问题。)
修改:实际上,看一下你的评论,这里有一个非常轻微的更微妙的问题,虽然结果是相同的(实际上强调了所有权的观点)
当您将字符串传递给setTitle
时,可以 retain
字符串本身,在这种情况下,此处调用release
可能不会导致崩溃立即。但是,你仍会过度释放,最终它会咬你。只是更难以找到问题的原因。
碰巧,setTitle
制作副本而不是保留你的副本。这在NSString
属性中很常见。一个原因是您可能会传递NSMutableString
,然后在稍后的某个时间点随机更改它可能会搞砸接收器。私人复制更安全。作为奖励,它会立即暴露您的过度释放,并允许您轻松修复它。
无论如何,重点是:只有release
你知道自己拥有的东西。如果您刚刚将它传递给其他对象,则该对象有责任处理它是否拥有它,而不是您的。
答案 1 :(得分:1)
您似乎对保留和释放工作有一些根本的误解。你说:
“当我尝试发布formattedDate时,为什么应用程序崩溃?我毕竟已经将它的引用传递给title属性”
“我需要发布dateformatter,因为......我还没有传递对它的引用”
您是否传递某个引用与您是否负责释放它无关。 memory management rules决定你是应该保留还是释放一些东西,它们几乎与传递引用无关。你应该阅读那份文件,因为它非常基础而且并不是那么难。一旦你明白了,所有关于这类事情的问题都将消失。
简言之,您拥有一个对象,并且如果您是通过new
alloc
或copy
方法获得的,或者retain
它。对于NSDateFormatter,您可以从alloc
获取它,因此您必须将其释放。对于字符串,这些都不是真的,因此您必须不发布您不拥有的此对象。
答案 2 :(得分:0)
略有不相关,但......
ObjC中的初始化器应该看起来像
- (id)init;
{
self = [super init];
if (self == nil)
return self;
...
return self;
}
这允许超类返回替换。这是ObjC的非常先进的用法,但坚持这种模式是一个好习惯。