Updates
19th August 2015 - Bug seems to have now been fixed in the 3.13
update, even though the only thing they list in their changelog is "Fixed an issue which caused crashes when using setCampaignParametersFromUrl"
. Take that as you will.
8th June 2015 - Still encountering this problem. If I disable automatic sending of events ([GAI sharedInstance].dispatchInterval = -1;
) then I still receive errors. I assume, therefore, that the problem lies with inserting the event into the Google Analytics SQLite database, that somehow my own database statement that is currently in progress are becoming void
.
10th June 2015 - Still encountering crashes. Tried removing my controllers extending GAITrackedViewController
and sending the createScreenView
track manually with no change in crash frequency.
25th June 2015 - Still encountering crashes.
Intro
I have added the Google Analytics SDK 3.12
to my iPhone app and everything is working as expected - I run the app and can see all of the hits and events that I have setup coming through on the Web interface.
I am initialising the SDK in my AppDelegate
right at the top of my didFinishLaunchingWithOptions
, like so:
[[GAI sharedInstance] trackerWithTrackingId:GOOGLE_ANALYTICS_ID];
The problem
However, I have found that running Google Analytics creates errors when I try and use SQLite for myself. They can manifest as serious errors such as:
"Database disk image is malformed"
and then insta-crashes"Disc i/O error"
whenever I run a query (though doesn't crash)
And they can also cause my own SQLite queries to just fail, for instance:
if (! sqlite3_prepare_v2(_db, [sql UTF8String], -1, &_statement, NULL) == SQLITE_OK) {`
// ..
// ..
if (sqlite3_step(_statement) == SQLITE_ROW) {
Will result, randomly, in the following error:
sqlite3_prepare_v2 EXC_BAD_ACCESS (code=1, address=0x6800000000)
If I comment out the SDK initialisation then everything goes back to being incredibly stable. Uncomment it again and it will crash the app within a minute.
Pre-emptive question answering
Am running this on a iPhone 6 running 8.3 (12F70).
Have tried uninstalling and reinstalling the app.
I have added all of the pre-requisites for Google Analytics to work; all of the
.m
files to the library, thelibGoogleAnalyticsServices.a
file, and also theLinked Frameworks and Libraries
.I also have Crashlytics, but have tried commenting it out from the code (
[Fabric with:@[CrashlyticsKit]];
) and removing its library from theLinked Frameworks and Libraries
with exactly the same results.
Code
Setting up the class
// In didFinishLaunchingWithOptions
[Db setup];
[Db connect];
Accesses the class
Db * db = [[Db alloc] init];
if ([db prepare:@"SELECT * FROM `table` WHERE `id` = ?" withBindings:@[@"123"]]) {
while ([db stepThrough]) {
// ..
}
}
[db finalise];
The class
(Have indicated where the errors appear with comments)
@implementation Db
static sqlite3 * _db;
static NSString * _dbPath;
#pragma mark - Setup
+ (BOOL)setup {
NSString * sqlBundlePath = [[NSBundle mainBundle] pathForResource:@"db" ofType:@"sqlite"];
NSString * documentsFolder = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString * sqlDocumentPath = [[documentsFolder stringByAppendingPathComponent:@"db"] stringByAppendingPathExtension:@"sqlite"];
NSFileManager * fileManager = [NSFileManager defaultManager];
if (! [fileManager fileExistsAtPath:sqlDocumentPath]) {
NSError * error;
BOOL success = [fileManager copyItemAtPath:sqlBundlePath toPath:sqlDocumentPath error:&error];
if (! success) {
return NO;
}
}
_dbPath = sqlDocumentPath;
return YES;
}
+ (BOOL)connect {
sqlite3_config(SQLITE_CONFIG_SERIALIZED);
return sqlite3_open([_dbPath UTF8String], &_db);
}
#pragma mark - Querying
- (BOOL)prepare:(NSString *)sql withBindings:(NSArray *)bindings {
// ERROR CAN OCCUR ON THE FOLLOWING LINE
if (! sqlite3_prepare_v2(_db, [sql UTF8String], -1, &_statement, NULL) == SQLITE_OK) {
NSLog(@"Error whilst preparing query: %s", sqlite3_errmsg(_db));
sqlite3_finalize(_statement);
return NO;
}
for (int i = 0; i < [bindings count]; i++) {
sqlite3_bind_text(_statement,
i + 1,
[bindings[i] isKindOfClass:[NSNull class]] ? [@"" UTF8String] : [bindings[i] UTF8String],
-1,
SQLITE_TRANSIENT);
}
return YES;
}
- (BOOL)stepThrough {
// ERROR CAN OCCUR ON THE FOLLOWING LINE
if (sqlite3_step(_statement) == SQLITE_ROW) {
return YES;
}
sqlite3_finalize(_statement);
return NO;
}
- (void)finalise {
sqlite3_finalize(_statement);
}
@end