Question

I am creating a class for my iOS application that deals with all my database functions. I have a single class method, for now, that saves data. In it, I create a database and a table. Then, I begin to save data. This happens every time this method is called. However, I am only dealing with a single database with a single table, so I want all this to happen only once.

#import <sqlite3.h>
#import "LocalDatabase.h"

@implementation LocalDatabase

+ (void)saveData:(id)sender {
    /* create database (if it doesnt exist) */
    sqlite3 *database = nil;
    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"db.sql"];
    if(sqlite3_open([path UTF8String], &database) != SQLITE_OK) {
        NSLog(@"Failed to open database");
    }

    /* create table (if it doesnt exist) */
    char *err;
    NSString *statement = @"CREATE TABLE IF NOT EXISTS DATA (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, CATEGORY TEXT)";
    if (sqlite3_exec(database, statement, NULL, NULL, &err) != SQLITE_OK) {
        NSLog(@"Failed to create table");
    }

    /* save data */
    // some code that uses database
}

@end

I do not know much about how static variables work in Objective, but I think the following code is correct:

#import "A.h"

@implementation A

static NSString *b = @"TEXT!!";

+ (void) c {
    //do stuff with b
}

@end

I believe this assigns @"TEXT!!!" to the NSString *b only once. I thought I could use this to solve my problem. However, I realized that the following does not compile:

#import "A.h"

@implementation A

static NSString *b = [NSString stringWithFormat:@"%@",@"TEXT!!!"];

+ (void) c {
    //do stuff with b
}

@end

This means that I cannot make a method call in the assignment that way. Also, I cannot have if-statements and such. Is there any way I can do these only once the same way it does static NSString *b = @"TEXT!!"; only once? Of course I can create a seperate class method just for initialization or create a static boolean that keeps track of whether I have initialized yet, but I was wondering if there is a cleaner way.

Was it helpful?

Solution

Use something like this inside of your method:

static dispatch_once_t pred;
dispatch_once(&pred, ^{
    // stuff to do only once
});

OTHER TIPS

+ (instancetype)sharedDatabase {
   static LocalDatabase *_sharedDatabase = nil;
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
    _sharedDatabase = [[self alloc] init];
   });

  return _sharedDatabase;
}

it will return a instance for your class LocalDatabase.

dispatch_once reference

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top