Should we release NSDate manually?
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 releas开发者_运维技巧e 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?
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.
Calling [ self.selectedDate release ]
will decrement the retain count of the object in self.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:
-(void)setSelectedDate:(NSDate*)date
{
[ selectedDate release ] ; // refers to the generated selectedDate instance variable in this class
selectedDate = [ date retain ] ;
}
Finally if you don't need atomic access (which you don't in most cases), use this nonatomic
declaration instead:
@property ( nonatomic, retain ) NSDate * date
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:
[selectedDate release];
selectedDate = nil;
OR
self.selectedDate = nil;
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
[selectedDate release];
Instead of
[self.selectedDate release];
精彩评论