关于iphone:NSDate alloc init

NSDate alloc init & getting message sent to deallocated instance

我知道获得新 NSDate 的首选方式是 [NSDate 日期]。但我只是很困惑为什么下面的代码会抛出异常"发送到已释放实例的消息"

1
2
3
4
5
6
7
8
9
10
11
12
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"MM/dd/yyyy"];
NSDate *dateFromStr = [[NSDate alloc] init];
// produce date object

dateFromStr = [dateFormatter dateFromString:self.releaseDate];

[dateFormatter setDateFormat:@"MM.dd.yyyy"];
NSString *strDate = [dateFormatter stringFromDate:dateFromStr];

[dateFormatter release];
[dateFromStr release];

此代码位于视图控制器中,被另一个视图控制器用作"虚拟"视图。类似于此:http://cocoawithlove.com/2009/01/multiple-virtual-pages-in-uiscrollview。 html


您的第一个问题是您通过分配 NSDate 对象来声明 dateFromStr,然后在将第一次调用的结果分配给 dateFromStr: 时泄漏该对象。您可以这样简化(并消除泄漏):

1
NSDate *dateFromStr = [dateFormatter dateFromString:self.releaseDate];

你需要知道的是你没有分配这个对象,所以你不需要释放它。除非您调用像 alloc 这样的方法(还有其他几个方法;在 SO 中搜索有关内存管理的其他帖子),否则您不负责释放该对象。

所以在你发布的代码中,最后一行是释放一个你没有分配的对象并导致你的错误。


1
2
3
4
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"MM/dd/yyyy"];
NSDate *dateFromStr = [[NSDate alloc] init];
// produce date object

在这里你正在创建一个 dateFromStr,我们称他为"John"。

1
dateFromStr = [dateFormatter dateFromString:self.releaseDate];

[NSDateFormatter dateFromString] 将返回一个新对象 "Tom",它已经被自动释放。您丢失了对已泄露的"John"的任何引用。

1
2
3
4
5
[dateFormatter setDateFormat:@"MM.dd.yyyy"];
NSString *strDate = [dateFormatter stringFromDate:dateFromStr];

[dateFormatter release];
[dateFromStr release];

在这里,您正在向已经 [autoreleased] 的对象发送 [release] 消息。最终结果是您将在 "Tom" 上调用 [release] 两次,在 "John" 上调用零次。

你可以这样重写你的代码:

1
2
3
4
5
6
7
8
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:@"MM/dd/yyyy"];

// produce date object
NSDate *dateFromStr = [dateFormatter dateFromString:self.releaseDate];

[dateFormatter setDateFormat:@"MM.dd.yyyy"];
NSString *strDate = [dateFormatter stringFromDate:dateFromStr];


代替

1
2
3
NSDate *dateFromStr = [[NSDate alloc] init];
// produce date object
dateFromStr = [dateFormatter dateFromString:self.releaseDate];

你应该只使用

1
NSDate *dateFromStr = [dateFormatter dateFromString:self.releaseDate];

否则,您将覆盖对象并丢失旧对象的地址。
之后,您尝试手动释放新的,然后垃圾收集器尝试释放它。而您的第一个分配对象正在泄漏。