self.ridesDict = [self loadHistoryFromDBExtended];
NSLog(@"rides dict %@", self.ridesDict); pre>However, I don’t want to call [self loadHistoryFromDBExtended] for each unit being loaded, because the dictionary will not change, so I try to move:
self.ridesDict = [self loadHistoryFromDBExtended];to viewDidLoad, now I receive an EXC_BAD_ACCESS error when I use it:
NSLog(@"rides dict %@", self. ridesDict);In the tableView: cellForRowAtIndexPath: indexPath. From what I can see, it seems that I have some memory retention/release issues, but I can’t seem to figure it out. After calling the loadHistoryFromDBExtended method, I’m in I tried [self.ridesDict retain] in viewDidLoad, but it did not help. I am very new to this, so I appreciate any suggestions on where to go.
Edit: This is the loadHistoryFromDBExtended method:
-(NSMutableDictionary *)loadHistoryFromDBExtended
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
FMDatabase* db = [FMDatabase database WithPath:[self getDBPath]];
if (![db open])
{
NSLog(@"Could not open db.");
[ pool release];
}
//get users
FMResultSet *rs = [db executeQuery:@"SELECT * FROM R order by date desc"]; //query provides result set
//create result array
NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] init];
while ([rs next])
{
NSMutableArray *usersDictArray = [NSMutableArray array];
//look up names for id's
[usersDictArray addObject:[rs stringForColumn:@"rNames"]];
[usersDictArray addObject:[rs stringForColumn:@"dName"]];
[usersDictArray addObject:[rs stringForColumn:@"date"]];
[myDictionary setObject:usersDictArray forKey:[rs stringForColumn :@"rID"]];
[usersDictArray release];
}
//return usersArray;
return myDicti onary;
[myDictionary release];
[pool drain];
}
This may be how I implemented it:< /p>
-(NSMutableDictionary *)loadHistoryFromDBExtended {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
FMDatabase* db = [FMDatabase databaseWithPath:[self getDBPath]];
if (![db open])
{
NSLog(@"Could not open db.");
[ pool release];
return nil; // I'm assuming you should return nil here
}
//get users; query provides result set
FMResultSet * rs = [db execut eQuery:@"SELECT * FROM R order by date desc"];
//create result array
NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] init];
while ([rs next])
{
NSMutableArray *usersDictArray = [NSMutableArray array];
//look up names for id's
[usersDictArray addObject:[rs stringForColumn: @"rNames"]];
[usersDictArray addObject:[rs stringForColumn:@"dName"]];
[usersDictArray addObject:[rs stringForColumn:@"date"]];
[ myDictionary setObject:usersDictArray forKey:[rs stringForColumn:@"rID"]];
// [usersDictArray release];
}
[pool drain];
return [myDictionary autorelease ];
)
(Please note how I achieve this. Assuming that the reason behind creating a local autorelease pool is to improve performance, and there is a global NSAutoreleasePool to absorb the final [myDictionary autorelease ]Auto release object).
I am trying to fix the EXC_BAD_ACCESS error thrown when I access the NSMutableDictionary in the tableView: cellForRowAtIndexPath: indexPath. Now, when I use the method loadHis When toryFromDBExtended fills in ridesDict, it works normally:
self.ridesDict = [self loadHistoryFromDBExtended];
NSLog(@"rides dict %@", self.ridesDict);
However, I don’t want to call [self loadHistoryFromDBExtended] for each unit being loaded, because the dictionary will not change so I try to move:
self.ridesDict = [self loadHistoryFromDBExtended];
to viewDidLoad, now I receive an EXC_BAD_ACCESS error when I use it:
NSLog (@"rides dict %@", self.ridesDict);
In tableView: cellForRowAtIndexPath: indexPath. From what I can see, it seems that I have some memory retention/release issues, but I can’t seem to Figured it out. After calling the loadHistoryFromDBExtended method, I tried [self.ridesDict retain] in viewDidLoad, but it did not help. I am very new to this, so I appreciate any suggestions on where to go.
Edit: This is the loadHistoryFromDBExtended method:
-(NSMutableDictionary *)loadHistoryFromDBExtended
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];< br />
FMDatabase* db = [FMDatabase databaseWithPath:[self getDBPath]];
if (![db open])
{
NSLog(@" Could not open db.");
[pool release];
}
//get users
FMResultSet *rs = [db executeQuery:@"SELECT * FROM R order by date desc"]; //query provides result set
//create result array
NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] init];
while ([rs next])
{
NSMutableArray *usersDictArray = [NSMutableArray array];
//look up names for id's
[usersDictArray addObject:[rs stringForColumn:@"rNames"]];
[usersDictArray addObject:[rs stringForColumn:@"dName"]];
[usersDictArray addObject:[rs stringForColumn:@"date"]];
[myDictionary setObject:usersDictArray forKey:[rs stringForColumn:@"rID"]];
[usersDictArray release];
}
//return usersArray;
return myDictionary;
[myDictionary release] ;
[pool drain];
}
There are many questions about how to implement this method. After checking whether it can be When opening the database, release the auto-release pool, and then continue to execute the rest of the code. I think you might want to return nil at that time. In the [rs next] section, you will create an NSMutableArray with an array, which creates an auto-released object. Therefore, you should not call [usersDictArray release] because of this Will be over-released. (In each cycle, "temporary", automatically released usersDictArray instance will be stored in the pool auto-release pool. When you call [pool drain], the auto-release pool will send a release message to all these temporary instances ). Near the end, you return to myDictionary;, which will never touch the next two lines. Therefore, the auto-release pool you created will never be released (popped).
This It may be the way I implemented it:
-(NSMutableDictionary *)loadHistoryFromDBExtended {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
< br /> FMDatabase* db = [FMDatabase databaseWithPath:[self getDBPath]];
if (![db open])
{
NSLog(@"Could not open db .");
[pool release];
return nil; // I'm assuming you should return nil here
}
//get users; query provides result set
FMResultSet *rs = [db executeQuery:@"SELECT * FROM R order by date desc"];
//create result array
NSMutableDictionary *myDictionary = [ [NSMutableDictionary alloc] init];
while ([rs next])
{
NSMutableArray *usersDictArray = [NSMutableArray array];
//look up names for id's
[usersDictArray addObject:[rs stringForColumn:@"rNames"]];
[usersDictArray addObject:[rs stringForColumn:@"dName"]];
[usersDictArray addObject:[rs stringForColumn:@"date"]];
[myDictionary setObject:usersDictArray forKey:[rs stringForColumn:@"rID "]];
// [usersDictArray release];
}
[pool drain];
return [myDictionary autorelease];
}
(Please note, how I achieve this assumes that the reason behind creating a local autorelease pool is to improve performance, and there is a global NSAutoreleasePool to absorb the final [myDictionary autorelease] autorelease object).