EXC_BAD_ACCESS with NSManagedObject - iphone

i am trying to insert values in a number of tables (25 to be exact), i am able to insert records in all the table except for one, and that is because of one single Attribute, if i remove that attribute it starts saving the data into the table but when i add that attribute and try to set its value, it terminates with EXC_BAD_ACCESS.
i tried changing the name of the attribute even the table's, but didnt work. below is my code::
Ashes *ashesObj = (Ashes *)[NSEntityDescription insertNewObjectForEntityForName:#"Ashes" inManagedObjectContext:managedObjectContext];
[ashesObj setAshes_id:#""];
[ashesObj setArrangement_id:#"34"];
[ashesObj setCasket_order_date:#""];
[ashesObj setCasket_model:#""];
[ashesObj setCasket_supplier:#""];
//[ashesObj setAshes_address:#"N/A"]; (This one is causing problem)
[ashesObj setPostal_code:#"N/A"];
[ashesObj setName_client:#""];
[ashesObj setTelephone:#""];
[ashesObj setEmail:#""];
NSError *error;
if (![managedObjectContext save:&error])
{
NSLog(#"Problem saving: %#", [error localizedDescription]);
}

General best practice, ANYTIME you run into a EXEC_BAD_ACCESS immediately run your code (and the same click/code path) through Instruments using the tool Zombies.
Do this with that line of code uncommented. Your app will crash, but Instruments and Zombies will point you to the exact line of code that is causing the crash (which will be different than the one you have there).
Most likely you are accidentally over releasing an object, and for whatever reason, it's only being exposed when you execute the code above.
You can launch Instruments from XCode using the Product menu, and select Profile. Once Instruments starts up, you'll be prompted for the tool to use, select Zombies. Then once the simulator appears, execute the test case to reproduce the issue. Once the crash happens, you'll see info from Zombies.

Related

sqlite prepare statement error - no such table

I'm having some difficulty with my sqlite prepare statement. I get an error saying my table does not exist, although I've checked in multiple places for it, and it does exist, so I'm confuzzled.
The file is in the correct iPhone Simulator Application folder
The file is added to my project and viewable in the project navigator
It is also in my build phases- Copy Bundle Resources area.
I've cleaned and started running again.
The database exists and running my sql statement gets me just the
results I expected.
- (NSMutableArray *) getMyWorkout{
NSMutableArray *workoutArray = [[NSMutableArray alloc] init];
#try {
NSFileManager *fileMgr = [NSFileManager defaultManager];
NSString *dbPath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:#"IOSDB.sqlite"];
NSLog(#"Db path is %#",dbPath);
BOOL success = [fileMgr fileExistsAtPath:dbPath];
if(!success) {
NSLog(#"Cannot locate database file '%#'.", dbPath);
}
if(!(sqlite3_open([dbPath UTF8String], &db) == SQLITE_OK)){
sqlite3_close(db);
NSLog(#"Failed to open database with message '%s'.", sqlite3_errmsg(db));
}
const char *sql = "SELECT Id, type, difficulty, duration, description FROM workoutTbl";
sqlite3_stmt *sqlStatement;
if(sqlite3_prepare(db, sql, -1, &sqlStatement, NULL) != SQLITE_OK){
NSLog(#"%s Prepare failure '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(db), sqlite3_errcode(db));
} //...
When I run it, I get the file path and the following error
2013-02-01 18:07:08.060 TriShake[9251:c07] -[MyWorkoutList getMyWorkout] Prepare failure 'no such table: workoutTbl' (1)
I've checked out these other questions, but have been unable to find a solution
Sqlite Prepare Failed: no such table<tablename>
Sqlite3 gives "no such table" error on iPhone
I understand sqlite3_open() creates an empty database for you if the database path does not exist, but i know it exists, so frustration ensues. Any help or guidance you could give me would be much appreciated.
In terms of your immediate problem, it's going to be something simple.
You say you've "cleaned and built again", but have you actually removed the old app from your simulator? Either remove the app manually, or, easier, just reset the simulator entirely by choosing "reset content and settings" from the "iOS Simulator" menu. Sometimes Xcode is not good about knowing what files to copy over (particularly in a case like this where your running it on the device may be changing the timestamp of the file in the simulator's bundle!)
Run the app again.
If the app doesn't work as expected, open up the database in the simulator folder from the Mac and check out the database to make sure the table is there and precisely as you expected it to be. So navigate to the app, open the bundle (you may have to choose the "show package contents" option), confirm the existence of the database, but just as importantly, open it up this particular copy of the database in your favorite Mac sqlite3 tool of choice and confirm the existence of the table there.
Let us know what you find. Again, it's got to be something simple such as:
Perhaps the process of rebuilding the app was not reinstalling everything; I've occasionally had problems where Xcode elected to not re-copy something during the install on my simulator;
Perhaps your database in your project was accidentally put in a subdirectory, worse, you might have two copies sitting in different directories;
Perhaps the database in your Xcode project is missing (or has a typo or (esp in the case of the device) has incorrect filename capitalization) in the name of the table or file;
Etc.
For a lot of these errors, you won't notice the problem until you completely reset the simulator itself. There are a million little things it could be, but hopefully completely resetting the simulator and starting over will help you find the issue. It's always something simple when it comes to these sorts of issues.
Some other minor observations:
You probably should not be opening databases from the bundle. Programmatically copy it from the bundle to the Documents folder, and open the database from there. I know it seems unnecessary, but it's important for a myriad of reasons (if db changes during operation of the app, if db accidentally gets created on you, don't let Xcode get confused about things that changed (even if only file timestamps) in the bundle changing behind Xcode's back, etc.)
You should, if you need the database to be there, use sqlite3_open_v2, using either SQLITE_OPEN_READWRITE or SQLITE_OPEN_READONLY for flags (but do not include SQLITE_OPEN_CREATE). It causes headaches to ever give sqlite a chance to create a blank database for you, or otherwise modify it, so never give it an opportunity to so.
I have encounter the same problem as yours. If the IOS can not find the designated database file, defaultly it will create one for you instead of throwing an error. So you must open the database file IOS created for you which is blank so it off course contain the table you expected.
what I deal with it :
1 you have to bundle the resource file named *.sqlite3 into your project
2 Then You have to use [NSBundle mainBundle] pathFordirectory...... function to search your proper database file.
then you can open the database file you expected and can operate it properly
Best regards,
Not enough rep to comment on Jack's post, but that helped me.
In my case, I had mistyped my path for resource extension:
// Wrong
NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:#"productList"
ofType:#"sqlite3"];
// Should have been (added db ext)
NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:#"productList"
ofType:#"db"];
I would always get past the:
if (sqlite3_open([sqLiteDb UTF8String], &_database) == SQLITE_OK))
because it was automatically creating a db file for me.

core data exc_bad_access when setting relationships

I have a problem with core data when setting relationships:
The code below crashes randomly when setting the relationships between country and region.
If I disable the second for-loop, the method completes without errors.
Everything happens within the context living on the background-thread.
Again: I can create the objects for the regions and countries without trouble and they show up in the Simulators database just fine - but as soon as I try to set the relationships between then, the app crashes randomly.
Any thoughts ?
for (Region* region in regions) {
// only store if region code isn't empty
if (region.m_RegionCode != nil && [region.m_RegionCode length] > 0) {
NSManagedObject* cdRegion = [NSEntityDescription insertNewObjectForEntityForName:CDREGION inManagedObjectContext:self.objectContextBackground];
[cdRegion setValue:region.m_RegionCode forKey:#"code"];
[cdRegion setValue:region.m_regioncodedescription forKey:#"name"];
}
}
[self saveBackgroundContext];
for (Region* region in regions) {
if (region.m_RegionCode != nil && [region.m_RegionCode length] > 0) {
NSManagedObject* cdRegion = [self getManagedObject:CDREGION withCode:region.m_RegionCode];
NSManagedObject* CDCountry = [self getManagedObject:CDCOUNTRY withCode:region.m_countrycode];
[cdRegion setValue:CDCountry forKey:#"country"];
}
}
well - just to let you know: it actually was the problem (I know - it is listed on top of all pages regarding this topic :-) that I used a context between threads.
I mixed up queues and threads. I created a single background-queue where I used my "background-context" ... but of course i created several threads within that, who where interacting with the context... so...
btw: it was this excellent article that finally clarified it for me:
(came right in time :-)
http://www.cimgf.com/2011/08/22/importing-and-displaying-large-data-sets-in-core-data/
This error message is likely related to memory problem, about using (or releasing) already deallocated object.
You should run profiler to spot the memory problem, or debug with a breakpoint after the save method and following a line by line execution until it crashes.
Just guessing, if you are creating or getting the Regions object with some sort of factory method, probably it gets deallocated in the middle of execution by that method, sometimes the routine is fast enough to complete before the dealloc, sometimes not, that could explain the randomness.
Try to retain the Regions at the beginning and release at the end of the second loop.

EXC_MEMORY_ACCESS when trying to delete from Core Data ($cash solution)

I have an application that downloads an xml file, parses the file, and creates core data objects while doing so. In the parse code I have a function called 'emptydatacontext' that removes all items from Core Data before creating replacements items from the xml data. This method looks like this:
-(void) emptyDataContext
{
NSFetchRequest * allCon = [[NSFetchRequest alloc] init];
[allCon setEntity:[NSEntityDescription entityForName:#"Condition" inManagedObjectContext:managedObjectContext]];
NSError * error = nil;
NSArray * conditions = [managedObjectContext executeFetchRequest:allCon error:&error];
DebugLog(#"ERROR: %#",error);
DebugLog(#"RETRIEVED: %#", conditions);
[allCon release];
for (NSManagedObject * condition in conditions) {
[managedObjectContext deleteObject:condition];
}
// Update the data model effectivly removing the objects we removed above.
//NSError *error;
if (![managedObjectContext save:&error]) {
DebugLog(#"%#", [error domain]);
}
}
The first time this runs it deletes all objects and functions as it should - creating new objects from the xml file. I created a 'update' button that starts the exact same process of retrieving the file the proceeding with the parse & build. All is well until its time to delete the core data objects. This 'deleteObject' call creates a "EXC_BAD_ACCESS" error each time. This only happens on the second time through.
Captured errors return null. If I log the 'conditions' array I get a list of NSManagedObjects on the first run. On the second this log request causes a crash exactly as the deleteObject call does.
I have a feeling it is something very simple I'm missing or not doing correctly to cause this behavior. The data works great on my tableviews - its only when trying to update I get the crashes.
I have spent days & days on this trying numerous alternative methods. Whats left of my hair is falling out. I'd be willing to ante up some cash for anyone willing to look at my code and see what I'm doing wrong. Just need to get past this hurdle.
Thanks in advance for the help!
Did you save the context after removing the objects in the for loop? Be aware that deleteObject: does not delete the object immediately, it simply schedule it for deletion when changes are committed, i.e., when you save the context.
EDIT: Your problem may be related to how you present your data to the user on your table view. Without additional code is difficult to tell exactly (are you using NSFetchedResultsController or not?), but my guess is that the interaction between deleting the data and showing them on the table is not correct. Probably, what is happening is that your table is told to visualize your data, but then, when you delete them, you are not updating correctly the table.
Wow, so after a few days of testing I went down a path that led me to tracking down Zombies & memory mgmt. This was a situation where the errors I was recieving were leftover from issues in another area. When parsing the data and placing it into Core Data I released an object that was to be autoreleased. So any subsequent calls to that item within core data (save, deletec, etc) caused a crash. Thank you all for your help and I vow to pay closer attention with my memory mgmt calls.

CoreData the save method is not working

Im a creating an app for my iPhone using coredata.
I have a viewcontroller with an object i want to save that object to my FavoriteViewController.
By clicking a button favorite I want my object to be save into the managedObjectContext but I'm getting the following error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Attempted to perform another operation with a fetch already in progress'. *
My Code:
// Step 1: Create Object
Favorite * newFavorite = (Favorite*)[NSEntityDescription insertNewObjectForEntityForName:#"Favorite" inManagedObjectContext:managedObjectContext];
// Step 2: Set Properties
newFavorite.name = #"Company";
NSLog(#"%#",newFavorite);
// Step 3: Save Object
NSError *error = nil;
if (![newFavorite.managedObjectContext save:&error]) { // this is where the program crash
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
I am not sure what I'm doing wrong.
I am going to guess you have a UI element, such as a table, that activates a fetch when the UI is changed. For example, if you have a fetched results controller, any scrolling of the table can activate the fetched results controller's fetch.
You can't mutate a collection while iterating over that collection because the count of the iteration changes while the iteration is in process. A fetch iterates over the collection of objects matching its entity and predicate. If you insert an object while the fetch is working you will get an error.
Usually you see this problem with multiple threads but I think the UI might trigger the problem in the right set of circumstances.
You have probably changed something in your tables. If this is true, try to use the original values for the table Z_METADATA (Z_VERSION, Z_UUID, Z_PLIST), Z_PRIMARYKEY (Z_ENT)...

Can I use a keyPath in a predicate?

For some reason, this didn't work (although the keypath does exist):
The Entity is set on the Employee.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"department.departmentName == %#", departmentName];
[fetchRequest setPredicate:predicate];
NSError *fetchError = nil;
NSUInteger count = [moc countForFetchRequest:fetchRequest error:&fetchError]; // execution simply stops at this line, with no error or console log
Execution just stops at the last line above when asking for the count. I don't get an console log. Also I don't get any kind of exception. The execution just stops. There are no objects in the persistent store yet. So maybe it crashes because of it tries to follow a keypath in a nonexisting object? Does that make sense?
The line where GDB stops is this:
0x002a31cb <+0459> test %eax,%eax
Previously to that, I see a lot of NSSQLAdapter... calls in the stack trace. There's definitely something wrong.
Well, but when I set the Entity to the destination of the key path and then just do something like
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"departmentName == %#", departmentName];
then there is no problem and count simply is 0.
I've seen this "just stopping" behavior when you have a circular reference in your object graph. The fetch gets caught up in a loop. The compiler will usually warn you if this is the case but it doesn't stop you from running.
Make sure you also set the entity of the fetch request? with setEntity: