I have written a query that fires on viewWillAppear
. On coming back to that screen with a quick navigation is resulting in crash at sqlite3_prepare_v2
.
What I am assuming is that the crash is due to the previous query not finalized.
I am calling the database operation using dispatch_async
as I am first updating remote data and then saving it in database.
The code looks like this :
dispatch_queue_t myQueue = dispatch_queue_create("My Queue",NULL);
dispatch_async(myQueue, ^{
[self parseActivityResponse:data]; // Sqlite operation here
dispatch_async(dispatch_get_main_queue(), ^{
// Update the UI
if(loaderImageview)
[loaderImageview removeFromSuperview];
[tableActivities reloadData];
});
});
The query is as follows :
- (NSMutableArray*)GetAllInvitations:(NSString*)ActivityId
{
NSMutableArray *arrInvitations = [[NSMutableArray alloc]init];
sqlite3_stmt *statement = nil;
@try {
const char *sql = "SELECT * FROM Invitation where ActivityId = ?";
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
sqlite3_bind_text(statement, 1, [ActivityId UTF8String], -1, SQLITE_TRANSIENT);
while (sqlite3_step(statement) == SQLITE_ROW) {
char *dbString;
Invitation *invitation = [[Invitation alloc]init];
dbString = (char *)sqlite3_column_text(statement, 0);
NSString *Id = (dbString) ? [NSString stringWithUTF8String:dbString] : @"";
[invitation setId:Id];
dbString = (char *)sqlite3_column_text(statement, 1);
NSString *childName = (dbString) ? [NSString stringWithUTF8String:dbString] : @"";
[invitation setChildName:childName];
dbString = (char *)sqlite3_column_text(statement, 2);
NSString *response = (dbString) ? [NSString stringWithUTF8String:dbString] : @"";
[invitation setResponse:response];
dbString = (char *)sqlite3_column_text(statement, 3);
NSString *invitationId = (dbString) ? [NSString stringWithUTF8String:dbString] : @"";
[invitation setInvitationId:invitationId];
dbString = (char *)sqlite3_column_text(statement, 4);
NSString *isCoGaurdian = (dbString) ? [NSString stringWithUTF8String:dbString] : @"";
[invitation setIsCoGaurdian:isCoGaurdian];
dbString = (char *)sqlite3_column_text(statement, 5);
NSString *activityId = (dbString) ? [NSString stringWithUTF8String:dbString] : @"";
[invitation setActivityId:activityId];
dbString = (char *)sqlite3_column_text(statement, 6);
NSString *picture = (dbString) ? [NSString stringWithUTF8String:dbString] : @"";
[invitation setPicture:picture];
dbString = (char *)sqlite3_column_text(statement, 7);
NSString *invitationUserId = (dbString) ? [NSString stringWithUTF8String:dbString] : @"";
[invitation setInvitedUserId:invitationUserId];
dbString = (char *)sqlite3_column_text(statement, 8);
NSString *roleId = (dbString) ? [NSString stringWithUTF8String:dbString] : @"";
[invitation setRoleId:roleId];
dbString = (char *)sqlite3_column_text(statement, 9);
NSString *status = (dbString) ? [NSString stringWithUTF8String:dbString] : @"";
[invitation setStatus:status];
[arrInvitations addObject:invitation];
}
}
else
{
NSLog(@"Failed to create table: %s", sqlite3_errmsg(database));
}
}
@catch (NSException *exception) {
NSLog(@"Error in GetAllInvitations : %@", exception.description);
}
@finally {
sqlite3_finalize(statement);
}
return arrInvitations;
}
- (NSMutableArray*)GetAllActivities{
NSMutableArray *arrProjects = [[NSMutableArray alloc]init];
sqlite3_stmt *statement = nil;
@try {
const char *sql = "SELECT * FROM Activity";
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
NSLog(@"success");
while (sqlite3_step(statement) == SQLITE_ROW) {
.........
activity.arrInvitations = [self GetAllInvitations:activityId];
[arrProjects addObject:activity];
}
}
else
{
NSLog(@"Prepare-error #%i: %s", sqlite3_prepare_v2(database, sql, -1, &statement, NULL), sqlite3_errmsg(database));
}
}
@catch (NSException *exception) {
NSLog(@"Error in GetAllActivities : %@", exception.description);
}
@finally {
sqlite3_finalize(statement);
}
return arrProjects;
}
I am calling GetAllActivities from viewWillAppear
:
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self reloadData];
}
-(void)reloadData
{
[self getRemoteActivities:^(BOOL finished) {
if(finished){
if([TGProjectHandler hasExistingSession])
{
[self getActivities];
}
else
[self login];
}
}];
}
Your thoughts and solution ?
Create a serial queue with:
dispatch_queue_t myQueue = dispatch_queue_create("My Queue", DISPATCH_QUEUE_SERIAL);
and that should manage sequential access to the database.
One thing i notice is in viewWillAppear
you call method getActivities
but you paste a body of GetAllActivities
. It's kind of a long shot but you sure you call your GetAllActivities
method properly? And from where GetAllInvitations
method get called?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With