Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Data not being saved to core data

I am using Xcode 5 compiling exclusively for iOS 7.

I am reading data from a UTF8 txt file to populate a core data entity. After reading the data, I log it to the console. The data is there. I populate the entity and log the entity to the console. I save it. No error. No crash.

I see 3 files on the device:

  • MyDatabase.sqlite
  • MyDatabase.sqlite-shm
  • MyDatabase.sqlite-wal

When the app starts and MyDatabase.sqlite is created empty it has 40 kb. At this point the shm file is 32kb and the wal file is zero.

After I write the data to the database, the wal files grows to 1,7 Mb but the other two files keep their initial sizes or in other words, the data is not being saved to the database. I have confirmed that by inspecting the sqlite file with an external database viewer.

This is the code I am using:

// NSArray *arrayOfYears = ... 
// this contains an array of numbers read from the CSV file
// at this point the array contains numbers in text format

// NSArray *arrayOfBrands = ...
// this is an array of brands

for (int i=0; i<[arrayOfBrands count]; i++) {

            Cars *car = [NSEntityDescription insertNewObjectForEntityForName:@"Cars" inManagedObjectContext:context];

            car.brand = [arrayOfBrands objectAtIndex:i];
            car.year = [NSNumber numberWithInt:[[arrayOfYears objectAtIndex:i] integerValue]];

            NSError *error = nil;
            if (![context save:&error]) {
                // Handle the error.
                NSLog(@"error = %@", error);
            }
}

This produces no error or crash. It goes like it was saving. I have increased mySql debug level to 3 and this is what I see on console...

when the table is created empty

CoreData: annotation: Connecting to sqlite database file at "/var/mobile/Applications/BB22334C4-550A-4C44-B17A-3F02062EC687/Documents/MyDatabase.sqlite"
CoreData: annotation: creating schema.
CoreData: sql: pragma page_size=4096
CoreData: sql: pragma auto_vacuum=2
CoreData: sql: BEGIN EXCLUSIVE
CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA'
CoreData: sql: CREATE TABLE ZCARS ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZYEAR INTEGER, ZBRAND VARCHAR ) 
CoreData: annotation: Creating primary key table.
CoreData: sql: CREATE TABLE Z_PRIMARYKEY (Z_ENT INTEGER PRIMARY KEY, Z_NAME VARCHAR, Z_SUPER INTEGER, Z_MAX INTEGER)
CoreData: sql: INSERT INTO Z_PRIMARYKEY(Z_ENT, Z_NAME, Z_SUPER, Z_MAX) VALUES(1, 'Cars', 0, 0)
CoreData: sql: CREATE TABLE Z_METADATA (Z_VERSION INTEGER PRIMARY KEY, Z_UUID VARCHAR(255), Z_PLIST BLOB)
CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA'
CoreData: sql: DELETE FROM Z_METADATA WHERE Z_VERSION = ?
CoreData: details: SQLite bind[0] = 1
CoreData: sql: INSERT INTO Z_METADATA (Z_VERSION, Z_UUID, Z_PLIST) VALUES (?, ?, ?)
CoreData: details: SQLite bind[0] = 1
CoreData: details: SQLite bind[1] = "C6E2268B-6792-4298-B292-5025E5BDE31A"
CoreData: details: SQLite bind[2] = <NSData len=455>
CoreData: annotation: Saving new meta data; version = 1 ; UUID = C6E2268B-6792-4298-B292-5025E5BDE31A
CoreData: sql: COMMIT
CoreData: sql: pragma journal_mode=wal
CoreData: sql: pragma journal_mode=wal
CoreData: sql: pragma cache_size=200
CoreData: sql: SELECT Z_VERSION, Z_UUID, Z_PLIST FROM Z_METADATA

after saving one brand/year

CoreData: sql: BEGIN EXCLUSIVE
CoreData: sql: SELECT Z_MAX FROM Z_PRIMARYKEY WHERE Z_ENT = ?
CoreData: annotation: getting max pk for entityID = 4
CoreData: sql: UPDATE Z_PRIMARYKEY SET Z_MAX = ? WHERE Z_ENT = ? AND Z_MAX = ?
CoreData: annotation: updating max pk for entityID = 4 with old = 0 and new = 1
CoreData: sql: COMMIT
CoreData: sql: BEGIN EXCLUSIVE
CoreData: sql: INSERT INTO ZTABULEIRO(Z_PK, Z_ENT, Z_OPT, ZYEAR, ZBRAND) VALUES(?, ?, ?, ?, ?)
CoreData: details: SQLite bind[0] = (int64)1
CoreData: details: SQLite bind[1] = (int64)4
CoreData: details: SQLite bind[2] = (int64)1
CoreData: details: SQLite bind[3] = "FORD"
CoreData: details: SQLite bind[4] = (int64)1989
CoreData: sql: COMMIT
CoreData: annotation: Changing objectID 0x14e71730 <x-coredata:///Cars/t38FA86EE-4124-4FD7-A8C0-8CE7BBAC73782> to 0x14e73ef0 <x-coredata://C6E3368B-6792-4298-B292-5025E5BDE31A/Cars/p1>
CoreData: sql: pragma page_count
CoreData: annotation: sql execution time: 0.0014s
CoreData: sql: pragma freelist_count
CoreData: annotation: sql execution time: 0.0016s

one strange thing I see here is the year variable like int64 when I have defined it like integer 16. Why it is using integer 64 is beyond me...

The data is not being saved at all. The data is there. If I log the arrays of data to console I see the data. If I log the entities populated before saving I see the data.

I am testing this on a device running iOS 7. Thanks.

What am I missing? How do I debug that?

like image 752
Duck Avatar asked Sep 19 '13 07:09

Duck


People also ask

How do I save an object in Core Data?

To save an object with Core Data, you can simply create a new instance of the NSManagedObject subclass and save the managed context. In the code above, we've created a new Person instance and saved it locally using Core Data.

Where is Core Data saved?

The persistent store should be located in the AppData > Library > Application Support directory. In this example you should see a SQLite database with extension . sqlite. It is possible that you don't see the persistent store in the Application Support directory.

What does use Core Data mean?

Use Core Data to save your application's permanent data for offline use, to cache temporary data, and to add undo functionality to your app on a single device. To sync data across multiple devices in a single iCloud account, Core Data automatically mirrors your schema to a CloudKit container.

How do I enable Core Data in Xcode?

Get our help adding Core Data to your project So, with your existing project open, create a new project in Xcode (⇧⌘N) and select a Single View App, you can call it whatever you like as we'll be deleting it when we're done. You'll see the “Use Core Data” checkbox on the project options screen, make sure it is checked.


1 Answers

The data is being saved to the database if the write-ahead-log (wal) is increasing in size, See documentation here http://www.sqlite.org/draft/wal.html. What are you using to open the database file? You must use a tool that works with WAL journal mode. Rather than looking at the db files directly, try creating a new context and fetching your saved entities.

like image 86
Andy Etheridge Avatar answered Sep 21 '22 21:09

Andy Etheridge