iPhone – NSMutableDictionary causes EXC_BAD_ACCESS

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 loadHistoryFromDBExtended to fill the ridesDict, it works fine: < p>

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 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];
}

There are many questions about how to implement this method. When checking whether the database can be opened, release the auto-release pool, and then continue to execute the rest of the code. I think you might want to return at that time nil. 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 this will release excessively. (In each loop In, "temporary", the auto-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; , This will cause the next two lines to never be touched. Therefore, the auto-release pool you created will never be released (popped).

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).

Leave a Comment

Your email address will not be published.