我们应该手动发布 NSDate 吗?
我在头文件中使用以下配置声明了 NSDate:
# TestController.h
@interface TestController : UITableViewController{
NSDate *selectedDate;
NSManagedObject *task;
}
@property (nonatomic, retain) NSManagedObject *managedObject;
@property (retain) NSDate *selectedDate
@end
# TestController.m
@implementation TestController
- (void)viewDidLoad {
self.selectedDate = [managedObject valueForKey:@"title"];
}
- (void)viewDidUnload {
self.task = nil;
self.selectedDate = nil;
}
- (void)dealloc {
[self.task release]
[self.selectedDate release];
[super dealloc];
}
@end
据我了解,您应该释放分配、复制或保留的变量。由于我这里保留了变量数据,所以我在dealloc的时候释放。但是,最终抛出内存释放错误:
“[NSDate isNSDate]:消息发送到释放实例 0x6923750”
如果我没有手动释放它,它工作正常。我的问题是我应该释放这个场景的变量吗?
更新:
使用僵尸模板进行仪器测试,这是输出:
# Category Event Type RefCt Timestamp Address Size Responsible Library Responsible Caller
0 __NSDate Malloc 1 1331055104 0x895e9d0 16 CoreData -[NSSQLCore _prepareResultsFromResultSet:usingFetchPlan:withMatchingRows:]
1 __NSDate Retain 2 1333056000 0x895e9d0 0 Task -[TaskViewCell configureData:]
2 __NSDate Retain 3 3045008128 0x895e9d0 0 CoreData -[NSManagedObject(_NSInternalMethods) _newPropertiesForRetainedTypes:andCopiedTypes:preserveFaults:]
3 __NSDate Retain 4 3054921984 0x895e9d0 0 CoreData -[NSSQLRow copy]
4 __NSDate Release 3 3059244032 0x895e9d0 0 CoreData -[NSSQLOperation dealloc]
5 __NSDate Release 2 3059607040 0x895e9d0 0 CoreData -[NSKnownKeysDictionary1 dealloc]
6 __NSDate Retain 3 3715918848 0x895e9d0 0 CoreData -[NSManagedObject(_NSInternalMethods) _newPropertiesForRetainedTypes:andCopiedTypes:preserveFaults:]
7 __NSDate Retain 4 3727657984 0x895e9d0 0 CoreData -[NSSQLRow copy]
8 __NSDate Release 3 3730131200 0x895e9d0 0 CoreData -[NSSQLOperation dealloc]
9 __NSDate Release 2 3730286080 0x895e9d0 0 CoreData -[NSKnownKeysDictionary1 dealloc]
10 __NSDate Retain 3 4250617856 0x895e9d0 0 CoreData -[NSManagedObject(_NSInternalMethods) _newPropertiesForRetainedTypes:andCopiedTypes:preserveFaults:]
11 __NSDate Retain 4 4250759936 0x895e9d0 0 CoreData -[NSManagedObject setValue:forKey:]
12 __NSDate Release 3 4250761984 0x895e9d0 0 CoreData -[NSManagedObject setValue:forKey:]
13 __NSDate Retain 4 4260489984 0x895e9d0 0 CoreData -[NSSQLRow copy]
14 __NSDate Release 3 4263536896 0x895e9d0 0 CoreData -[NSSQLOperation dealloc]
15 __NSDate Release 2 4263687168 0x895e9d0 0 CoreData -[NSKnownKeysDictionary1 dealloc]
16 __NSDate Release 1 4656624128 0x895e9d0 0 Task -[TaskEditController dealloc]
17 __NSDate Retain 2 7570179840 0x895e9d0 0 CoreData -[NSManagedObject(_NSInternalMethods) _newPropertiesForRetainedTypes:andCopiedTypes:preserveFaults:]
18 __NSDate Retain 3 7570360064 0x895e9d0 0 CoreData -[NSManagedObject setValue:forKey:]
19 __NSDate Release 2 7570361088 0x895e9d0 0 CoreData -[NSManagedObject setValue:forKey:]
20 __NSDate Retain 3 7577499136 0x895e9d0 0 CoreData -[NSSQLRow copy]
21 __NSDate Release 2 7602608128 0x895e9d0 0 CoreData -[NSSQLOperation dealloc]
22 __NSDate Release 1 7602752256 0x895e9d0 0 CoreData -[NSKnownKeysDictionary1 dealloc]
23 __NSDate Release 0 7971558144 0x895e9d0 0 Task -[TaskEditController dealloc]
24 __NSDate Zombie -1 9697122048 0x895e9d0 0 Foundation -[NSDateFormatter stringForObjectValue:]
不太明白这意味着什么。但是,我的猜测是 coredata 即使保留了 NSDate 也会释放它吗?
I declared NSDate at my header file with following configuration:
# TestController.h
@interface TestController : UITableViewController{
NSDate *selectedDate;
NSManagedObject *task;
}
@property (nonatomic, retain) NSManagedObject *managedObject;
@property (retain) NSDate *selectedDate
@end
# TestController.m
@implementation TestController
- (void)viewDidLoad {
self.selectedDate = [managedObject valueForKey:@"title"];
}
- (void)viewDidUnload {
self.task = nil;
self.selectedDate = nil;
}
- (void)dealloc {
[self.task release]
[self.selectedDate release];
[super dealloc];
}
@end
For my understanding, you should release variables that is alloc, copy or retain. As I retain the variable data here, so I release when dealloc. But, end up throw memory deallocation error:
"[NSDate isNSDate]: message sent to deallocated instance 0x6923750"
If I didn't manually release it, its working fine. My question is should I release the variable for this scenario?
Update:
Did an instrument test with zombie templates and this is the output:
# Category Event Type RefCt Timestamp Address Size Responsible Library Responsible Caller
0 __NSDate Malloc 1 1331055104 0x895e9d0 16 CoreData -[NSSQLCore _prepareResultsFromResultSet:usingFetchPlan:withMatchingRows:]
1 __NSDate Retain 2 1333056000 0x895e9d0 0 Task -[TaskViewCell configureData:]
2 __NSDate Retain 3 3045008128 0x895e9d0 0 CoreData -[NSManagedObject(_NSInternalMethods) _newPropertiesForRetainedTypes:andCopiedTypes:preserveFaults:]
3 __NSDate Retain 4 3054921984 0x895e9d0 0 CoreData -[NSSQLRow copy]
4 __NSDate Release 3 3059244032 0x895e9d0 0 CoreData -[NSSQLOperation dealloc]
5 __NSDate Release 2 3059607040 0x895e9d0 0 CoreData -[NSKnownKeysDictionary1 dealloc]
6 __NSDate Retain 3 3715918848 0x895e9d0 0 CoreData -[NSManagedObject(_NSInternalMethods) _newPropertiesForRetainedTypes:andCopiedTypes:preserveFaults:]
7 __NSDate Retain 4 3727657984 0x895e9d0 0 CoreData -[NSSQLRow copy]
8 __NSDate Release 3 3730131200 0x895e9d0 0 CoreData -[NSSQLOperation dealloc]
9 __NSDate Release 2 3730286080 0x895e9d0 0 CoreData -[NSKnownKeysDictionary1 dealloc]
10 __NSDate Retain 3 4250617856 0x895e9d0 0 CoreData -[NSManagedObject(_NSInternalMethods) _newPropertiesForRetainedTypes:andCopiedTypes:preserveFaults:]
11 __NSDate Retain 4 4250759936 0x895e9d0 0 CoreData -[NSManagedObject setValue:forKey:]
12 __NSDate Release 3 4250761984 0x895e9d0 0 CoreData -[NSManagedObject setValue:forKey:]
13 __NSDate Retain 4 4260489984 0x895e9d0 0 CoreData -[NSSQLRow copy]
14 __NSDate Release 3 4263536896 0x895e9d0 0 CoreData -[NSSQLOperation dealloc]
15 __NSDate Release 2 4263687168 0x895e9d0 0 CoreData -[NSKnownKeysDictionary1 dealloc]
16 __NSDate Release 1 4656624128 0x895e9d0 0 Task -[TaskEditController dealloc]
17 __NSDate Retain 2 7570179840 0x895e9d0 0 CoreData -[NSManagedObject(_NSInternalMethods) _newPropertiesForRetainedTypes:andCopiedTypes:preserveFaults:]
18 __NSDate Retain 3 7570360064 0x895e9d0 0 CoreData -[NSManagedObject setValue:forKey:]
19 __NSDate Release 2 7570361088 0x895e9d0 0 CoreData -[NSManagedObject setValue:forKey:]
20 __NSDate Retain 3 7577499136 0x895e9d0 0 CoreData -[NSSQLRow copy]
21 __NSDate Release 2 7602608128 0x895e9d0 0 CoreData -[NSSQLOperation dealloc]
22 __NSDate Release 1 7602752256 0x895e9d0 0 CoreData -[NSKnownKeysDictionary1 dealloc]
23 __NSDate Release 0 7971558144 0x895e9d0 0 Task -[TaskEditController dealloc]
24 __NSDate Zombie -1 9697122048 0x895e9d0 0 Foundation -[NSDateFormatter stringForObjectValue:]
Didn't really understand what this mean. But, my guess is coredata releasing the NSDate even with retain?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
解决过度释放对象问题的最佳方法是启动 Instruments(在 XCode 中,键入 ⌘-I 而不是 ⌘-R)并选择“Zombies”模板 - 它会显示每个对象的位置被保留和释放,并告诉您代码何时向已释放的实例发送消息。
在这种情况下,不平衡的释放可能潜伏在代码中的其他地方,并且将释放放入 dealloc 方法中会暴露其他地方的问题。无论如何,您的问题的直接答案是“是的,您应该释放您保留的变量”,并且您在此处发布的代码具有正确的保留与释放比率(即一对一),因此我会寻找您可能发布此 NSDate 的其他地方。
The best way to troubleshoot a problem with over-releasing an object is to fire up Instruments (from within XCode, type ⌘-I instead of ⌘-R) and choose the "Zombies" template – it'll show you where each object is being retained and released, and tell you when your code sends a message to an already-released instance.
It's possible in this case that an unbalanced release is lurking somewhere else in your code, and putting a release in your dealloc method is exposing a problem that lies elsewhere. In any case, the direct answer to your question is "yes, you should be releasing the variable you retained," and the code you've posted here has the correct ratio of retains to releases (that is, one to one), so I'd look for other places where you might be releasing this NSDate.
调用
[ self.selectedDate release ]
将减少self.selectedDate
中对象的保留计数,但是self.selectedDate仍然包含对(现在过度释放)的引用日期对象。您应该这样做:
self.selectedDate = nil
。因为:
self.selectedDate = nil
对于此实际代码来说是方便的语法:
[ self setSelectedDate:nil ]
方法
setSelectedDate:
自动生成@synthesize selectedDate
。由于属性被声明为
retain
,生成的 setter 如下所示:最后,如果您不需要原子访问(大多数情况下不需要),请使用此
nonatomic
声明改为:Calling
[ self.selectedDate release ]
will decrement the retain count of the object inself.selectedDate
, however self.selectedDate still contains a reference to the (now over-released) date object.You should do this:
self.selectedDate = nil
.Because:
self.selectedDate = nil
is convenient syntax for this actual code:
[ self setSelectedDate:nil ]
The method
setSelectedDate:
is automatically generated by@synthesize selectedDate
.Since the property is declared
retain
, the generated setter looks like this:Finally if you don't need atomic access (which you don't in most cases), use this
nonatomic
declaration instead:是的,您应该释放您拥有的任何变量(分配、复制或保留)。然而,在 dealloc 方法中释放 NSDate 变量的正确方法应该是:
或
第二种方法将调用属性的选择器方法,该方法首先释放变量,然后将 nil 分配给处理程序。因此,这行代码将释放它并将其设置为 nil,就像第一个选项中的两行单独的行一样。
Yes, you should release any variable that you own (alloced, copied or retained). However, the proper way to release your NSDate variable in dealloc method should be either:
OR
The second approach will call the selector method of property which first releases the variable and then assign nil to the handler. So, this one line of code will both release it and set it to nil like the two separate lines in the first option.
尝试
代替
Try
Instead of