【发布时间】:2011-10-01 03:19:28
【问题描述】:
我一直在研究核心数据,并开始编写一些方法来查询不同日期范围的数据。我的核心数据模型非常简单(实体名为 Smoke,带有一个字段 - 时间戳(日期类型)。
当我执行我的代码时,会返回正确的计数,但我收到一个自动释放错误 - 我使用 NSZombies 将其跟踪到以下方法:
- (NSUInteger)retrieveSmokesForUnit:(NSCalendarUnit)unit
{
NSDate *beginDate = [[NSDate alloc] init];
NSDate *endDate = [[NSDate alloc] init];
[self rangeForUnit:unit containingDate:[NSDate date] startsAt:&beginDate andEndsAt:&endDate];
NSInteger count = [self numberOfSmokes:beginDate toDate:endDate];
[beginDate release];
[endDate release];
return count;
}
所以我明白了这个概念——我释放 NSDate 对象 beginDate 和 endDate 的次数太多了——但是为什么会这样呢?我认为规则是当你用 alloc 实例化时,你使用释放?我没有在代码的其他任何地方明确发布它们,所以幕后肯定有一些事情发生。如果有人能指出我正确的方向,那就太好了!
这里是涉及到的其他方法,因为问题肯定在这些方法中的某个地方。我认为这与我如何传递指向日期的指针有关?
初始调用,在视图控制器中调用
- (IBAction)cigButtonPressed
{
NSUInteger smokes = [[DataManager sharedDataManager] retrieveSmokesForUnit:NSWeekCalendarUnit];
NSLog(@"Count test = %i", smokes);
}
这个调用贴出问题开头的方法,依次调用:
- (NSUInteger)numberOfSmokes:(NSDate *)beginDate toDate:(NSDate *)endDate {
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Smoke" inManagedObjectContext:self.managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
//Create predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(timeStamp >= %@) AND (timeStamp < %@)", beginDate, endDate];
//Setup request
[request setEntity:entity];
[request setPredicate:predicate];
NSError *error;
NSUInteger smokes = [self.managedObjectContext countForFetchRequest:request error:&error];
NSLog(@"Number of smokes retrieved: %d", smokes);
[request release];
return smokes;
}
谢谢!
编辑 - 省略了相关方法:
- (void)rangeForUnit:(NSCalendarUnit)unit containingDate:(NSDate *)currentDate startsAt:(NSDate **)startDate andEndsAt:(NSDate **)endDate {
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar rangeOfUnit:unit startDate:&*startDate interval:0 forDate:currentDate];
*endDate = [calendar dateByAddingComponents:[self offsetComponentOfUnit:unit] toDate:*startDate options:0];
[calendar release];
}
【问题讨论】:
-
当我遇到自动释放问题(产生令人沮丧的调试信息)时,我设法通过在代码块周围创建和排出自动释放池来缩小问题(注意保留任何必须在
drain中持续存在)。你最终会找到一个小区域,你的游泳池会引发问题。 -
我能够将其缩小到 retrieveSmokesForUnit 中的 [beginDate release] 和 [endDate release] 行...如果我删除它们,它运行良好,没有崩溃...
-
啊,添加代码后问题就很明显了。您创建(保留的)日期对象,然后用 rangeForUnit 中的自动发布版本覆盖它们,然后释放自动发布的版本(让原始日期对象泄漏,顺便说一句)。
-
[calendar rangeOfUnit:unit startDate:&*startDate中的 & 不是错了吗? rangeOfUnit 不修改 startDate。 -
@ott 那
&*最终成为无操作并且可以被删除。
标签: iphone objective-c memory-management