deleteObject deletes but leaves empty rows in the sqlite3 database?
I need to delete the selected row of the database shown in updatePick
, but can't seem to get the managedObject
that's supposed to be in the [context deleteObject:managedObject];
line correct. Here's the deleteUpdate method:
-(void)deleteUpdate {
NSLog(@"35-Delete pressed.");
NSManagedObjectContext *context = [self managedObjectContext];
NSEntityDescription *updateEntity = [NSEntityDescription en开发者_运维技巧tityForName:@"Updates" inManagedObjectContext:context];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:updateEntity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(dateGains = %@)", [arrayNSDateGains objectAtIndex:updatePick]];
[fetchRequest setPredicate:predicate];
NSArray *gains = [context executeFetchRequest:fetchRequest error:nil];
for (updateGains in gains) {
[context deleteObject:updateGains];
}
[self saveContext];
}
This manages to delete the contents of the row in the database (YEAH), except, it leaves an empty row and three residual elements: primary key (Z_PK), and two integers (Z_ENT) & (Z_OPT). The empty row causes errors elsewhere. What am I missing here?
Core Data often leaves empty rows in sqlite stores after deletes. The documentation explicitly states that the store file will not grow smaller after deletes until at some arbitrary point the persistent store object decides to condense the store.
In general looking at the sqlite store itself is a waste of time. Core Data is not SQL. Entities are not tables. Objects are not rows. Attributes are not columns. Relationships are not joins. Core Data is an object graph management system that may or may not persist the object graph and may or may not use SQL far behind the scenes to do so. Trying to think of Core Data in SQL terms will cause you to completely misunderstand Core Data and result in much grief and wasted time.
Core Data merely has the option of serializing (freeze drying) object into an sqlite store. However, how it does that is not documented so looking at the sqlite store directly won't tell you much.
The only way to confirm that an object has been deleted is to get and save its permenent managedObjectID
. After the delete, ask the persistentStoreCoordinator to fetch the object for the id with objectWithID:
. If the object has been deleted, it won't find it.
There are only a couple of ways in which an object can remain after deletion. The undo manager can roll back apparent deletions but that isn't the case here. If you retain a managed object elsewhere, then the object in memory will remain after the deletion (although it won't show up in Core Data operations like a fetch.)
I doubt any problems you are having is caused by an issue with the store. Such issues are very rare.
Update:
After the save, I do a [self setNeedsDisplay]; which triggers a redrawing of the bar chart based on the data in the database. The first mutable array tries to insertObject:atIndex: a nil object which causes crash… I've inserted a if(dateGained==nil) continue; at the point where the next error had occurred and it works great.
Your problem here is that your UI controller is not updating its count of the managed objects after the context deletes some of them.
For example: You have a table that displays one Update
object per row. At the start the UI controller fetches all the existing Update
objects. It tells the table that it has [fetchObjects count]
. Then you delete some of the Update
objects but then you don't tell the table it has fewer rows now. The table will attempt to access objects in the array past the last element which causes a crash.
The solution here is to register your controller for the context's notification:
NSManagedObjectContextObjectsDidChangeNotification
… and then update the array and the tables row count before you call [self setNeedsDisplay]
.The table will then understand how many rows it should have.
Any UI element that depends on a count of the fetched objects needs to keep in sync with changes in object graph, especially deletes.
You forgot to fetch the entity. Do this:
NSArray *results = [context executeFetchRequest:request error:nil];
if (results) {
for (NSManagedObject *updateGains in results) {
[context deleteObject:updateGains];
}
[context save:nil];
}
[self saveContext];
精彩评论