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
您的第一个问题是您通过分配
1 | NSDate *dateFromStr = [dateFormatter dateFromString:self.releaseDate]; |
你需要知道的是你没有分配这个对象,所以你不需要释放它。除非您调用像
所以在你发布的代码中,最后一行是释放一个你没有分配的对象并导致你的错误。
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]; |
否则,您将覆盖对象并丢失旧对象的地址。
之后,您尝试手动释放新的,然后垃圾收集器尝试释放它。而您的第一个分配对象正在泄漏。