【发布时间】:2011-06-22 05:28:43
【问题描述】:
我正在开发一个使用 SQLite 数据库作为模型数据主要来源的 Iphone 应用程序。
当应用打开时,名为“Model”的单例对象扫描 SQLite 表,使用每一行创建一个“Result”对象(NSObject 子类),然后将每个 Result 添加到 NSMutableArray。
这是该部分的代码,在我找到数据库路径后立即开始:
- (void)populateResultArrayWith:(NSString *)dbPath {
const char *sql = "SELECT * FROM results";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
NSInteger pkInt = sqlite3_column_int(selectstmt, 0);
NSNumber *pk = [NSNumber numberWithInt:pkInt];
NSString *v = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
NSString *n = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)];
NSString *s = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 3)];
NSNumber *c = [NSNumber numberWithFloat:(float)sqlite3_column_double(selectstmt, 4)];
NSString *t1 = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 5)];
NSString *t2 = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 6)];
NSString *t3 = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 7)];
Result *resultObj = [[Result alloc] initWithPrimaryKey:(NSNumber *)pk
withVerb:(NSString *)v
withNoun:(NSString *)n
withSuffix:(NSString *)s
withCost:(NSNumber *)c
withTag1:(NSString *)t1
withTag2:(NSString *)t2
andTag3:(NSString *)t3];
[self.resultArray addObject:resultObj];
[resultObj release];
}
}
else
sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
NSLog(@"Model: Closing Database");
}
稍后,我的一个视图控制器告诉我的模型启动一个重复的 NSTimer,并触发一个从 NSMutableArray 生成随机结果的方法:
-(void)startTimer
{
if (startDate && startDate != nil) {
startDate = nil;
}
self.modelCumulativeValueWasted = 0;
startDate = [[NSDate date] retain];
modelTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0/1.0)
target:self
selector:@selector(tick)
userInfo:nil
repeats:YES];
[self randomResult];
}
还有:
-(Result *)randomResult
{
if (randomResult != nil) {
randomResult=nil;
}
NSLog(@"Selected Result Retain Count At Beginning of Method = %i", [randomResult retainCount]);
// Generate a random int between 0 and the total count of the resultArray.
int randomIndex = arc4random() % [resultArray count];
// Select a result from the resultArray at that index - with an iVar.
randomResult = [resultArray objectAtIndex:randomIndex];
NSLog(@"Selected Result Retain Count At End of Method= %i", [randomResult retainCount]);
return randomResult;
}
控制台读数告诉我,在此方法的过程中保留计数是正常的... randomResult 在打开 if/then 语句后以 0 的保留计数开始,在它具有 1 之后的保留计数开始被退回了。
然后我的模型根据其他模型数据应用一些计算来生成一个格式化的结果字符串以显示在视图中:
-(void)calculateQuantity
{
// Get the float of the randomly selected result's "cost" property.
selectedCostFloat = [randomResult.cost floatValue];
// Calculate "how many of this result item could we buy" by dividing the cumulativeValueWasted by the costFloat.
float quantityFloat = (modelCumulativeValueWasted / selectedCostFloat);
NSLog(@"Quantity Float = %f", quantityFloat);
// Save this float as an NSNumber object, so a NSNumberFormatter can interpret it in ResultVC.
quantityNumber = [NSNumber numberWithFloat:quantityFloat];
}
我的问题是每次调用这个方法,并且我的模型尝试获取 NSNumber *cost 属性的 floatValue 时,我都会崩溃(使用断点,我隔离了 calculateQuantity 的第一行: em> 作为崩溃点),我在控制台中收到以下消息:
-[CFNumber floatValue]:消息发送到已释放实例0x6332280
它的工作方式是 [sharedModel calculateQuantity]; 在计时器的第一个滴答声中被调用,然后它崩溃了:
-(void)tick
{
// For "Time" every tick
NSDate *currentDate = [NSDate date];
NSTimeInterval countInSeconds = [currentDate timeIntervalSinceDate:startDate];
[df setDateFormat:@"HH:mm:ss"];
[df setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSDate *modelTimerDate = [NSDate dateWithTimeIntervalSinceReferenceDate:countInSeconds];
self.modelTimeString = [df stringFromDate:modelTimerDate];
NSLog(@"Time String: %@",self.modelTimeString);
//For "$" every tick
self.modelCumulativeValueWasted += self.modelMeetingValuePerSecond;
self.modelNumberToDisplayString = [NSString stringWithFormat:@"$%1.2f",self.modelCumulativeValueWasted];
NSLog(@"Cumulative Money Wasted: %@",self.modelNumberToDisplayString);
[self calculateQuantity];
}
我不相信我会调用任何东西两次,而且我的内存管理看起来不错。
最令人困惑的部分是,如果我将 calculateQuantity 方法的前几行移动到 randomResult 方法的末尾,我仍然会崩溃。即使在控制台告诉我保留计数为 1 之后,它也会立即表示我正在尝试向已释放的实例发送消息。
我知道这似乎是一个经常出现的问题,但我无法从任何其他线程中找出问题所在。
【问题讨论】:
-
Result的initWith**方法是怎么写的?
标签: iphone ios memory-management nstimer dealloc