Piero
Piero

Reputation: 9273

Fast access to Core Data database information?

i have iOS application with core data, in one of my function i load the information to display one view of my application in this way:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription 
                               entityForName:@"MyDate" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];

NSError *error;

NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

for (NSManagedObject *info in fetchedObjects) {

    if ([[[info valueForKey:@"status"] description] isEqualToString:@"Done"]) {

        NSArray *allTask = [[info valueForKey:@"taskes"] allObjects];
        for (NSManagedObject *task in allTask) {
            NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
            [dateFormatter setDateFormat:@"yyyy-MM-dd"];

            if (IsDateBetweenInclusive([task valueForKey:@"firstDate"], fromDate, toDate)) {

                [taskArray addObject:task];
            }
        }
    }
}

so i iterate all database to find the information and then display it, when the information in my database are few the method above is fast, but when the information in my database is more, on my 3GS take some seconds to display that view, instead in the simulator is fast, so my question is, there is a fast way, to take information from core date? i don't know there is a fast call with the attribute and the value i want retrieve from core data?

thanks

Upvotes: 0

Views: 542

Answers (2)

chandrika
chandrika

Reputation: 394

Create database:

NSString *docsDir; NSArray *dirPaths;

dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

docsDir = [dirPaths objectAtIndex:0];
databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: @"newapp.sqlite"]];

NSFileManager *filemgr = [NSFileManager defaultManager];

if ([filemgr fileExistsAtPath: databasePath ] == NO)
{
    const char *dbpath = [databasePath UTF8String];

    if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
    {
        char *errMsg;
        const char *sql_stmt = "CREATE TABLE IF NOT EXISTS LIST (id VARCHAR, title VARCHAR , description VARCHAR ,date VARCHAR)";


        if ((sqlite3_exec(contactDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK) )
        {
            UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Warning" message:@"Failed to create table" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [alert show];
                        }

        sqlite3_close(contactDB);

    } else {
        UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Warning" message:@"Failed to open/create database" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];

    }
}

Insert values

NSString *id_str=@"21"; NSString *title=@"notisa"; NSString *description=@"new app"; NSString *date=@"21/4/30";

const char *dbpath = [databasePath UTF8String];

if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK){
    // error handling...
}
// Construct the query and empty prepared statement.
const char *sql = "INSERT INTO `LIST` (`id`,`title`,`description`,`date`) VALUES (?, ?, ?, ?)";
sqlite3_stmt *statement;

   // UIImage *image = [UIImage imageWithData:imgdata];
//NSData *imageData=UIImagePNGRepresentation(image);

// Prepare the statement.
if (sqlite3_prepare_v2(contactDB, sql, -1, &statement, NULL) == SQLITE_OK) {
    // Bind the parameters (note that these use a 1-based index, not 0).


    sqlite3_bind_text(statement,1, [id_str UTF8String], -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(statement,2, [title UTF8String], -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(statement,3, [description UTF8String], -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(statement,4, [date UTF8String], -1, SQLITE_TRANSIENT);

        }

// Execute the statement.
if (sqlite3_step(statement) != SQLITE_DONE) {
    // error handling...
    UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Warning" message:@"Failed to Save" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
       }
else
{
    UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Database" message:@"Stored Successfully" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
     }
// Clean up and delete the resources used by the prepared statement.
sqlite3_finalize(statement);
sqlite3_close(contactDB);

Select Database: const char *dbpath = [databasePath UTF8String]; sqlite3_stmt *statement;

if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
    NSString *querySQL = [NSString stringWithFormat: @"SELECT id,title,description,date FROM LIST"];

    const char *query_stmt = [querySQL UTF8String];

    if (sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
    {
        while(sqlite3_step(statement) == SQLITE_ROW)
        {
            NSLog(@"ROW-->%d",SQLITE_ROW);

            const char* policyNo  = (const char *)sqlite3_column_text(statement, 1);
            NSString *PolicyNumber = policyNo == NULL ? nil : [[NSString alloc]initWithUTF8String:policyNo];


            NSLog(@"PolicyNumber:%@",PolicyNumber);

            const char* start  = (const char *)sqlite3_column_text(statement, 2);
            NSString *startDate = start == NULL ? nil : [[NSString alloc]initWithUTF8String:start];

            const char* end  = (const char *)sqlite3_column_text(statement, 3);
            NSString *endDate = end == NULL ? nil : [[NSString alloc]initWithUTF8String:end];


                   }
        sqlite3_finalize(statement);
    }
    sqlite3_close(contactDB);
}

Delete :

const char *dbpath = [databasePath UTF8String]; sqlite3_stmt *statement;

if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
    NSString *querySQL = [NSString stringWithFormat: @"DELETE id,title,description,date FROM LIST"];

    const char *query_stmt = [querySQL UTF8String];

    if (sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
    {
        while(sqlite3_step(statement) == SQLITE_ROW)
        {
            NSLog(@"ROW-->%d",SQLITE_ROW);

            const char* policyNo  = (const char *)sqlite3_column_text(statement, 1);
            NSString *PolicyNumber = policyNo == NULL ? nil : [[NSString alloc]initWithUTF8String:policyNo];


            NSLog(@"PolicyNumber:%@",PolicyNumber);

            const char* start  = (const char *)sqlite3_column_text(statement, 2);
            NSString *startDate = start == NULL ? nil : [[NSString alloc]initWithUTF8String:start];

            const char* end  = (const char *)sqlite3_column_text(statement, 3);
            NSString *endDate = end == NULL ? nil : [[NSString alloc]initWithUTF8String:end];


        }
        sqlite3_finalize(statement);
    }
    sqlite3_close(contactDB);
}

Upvotes: 0

Frank
Frank

Reputation: 3376

Use NSPredicate, see https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/CoreData/Articles/cdFetching.html

The following piece of code will only fetch the values where the status field is set to 'Done'

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyDate" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"status == 'Done'"]];

NSError *error;

NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

Upvotes: 2

Related Questions