mardi 26 mai 2015

Google Analytics SDK creates SQLite errors

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

  1. Am running this on a iPhone 6 running 8.3 (12F70).

  2. Have tried uninstalling and reinstalling the app.

  3. I have added all of the pre-requisites for Google Analytics to work; all of the .m files to the library, the libGoogleAnalyticsServices.a file, and also the Linked Frameworks and Libraries.

  4. I also have Crashlytics, but have tried commenting it out from the code ([Fabric with:@[CrashlyticsKit]];) and removing its library from the Linked 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

Aucun commentaire:

Enregistrer un commentaire