As I continue to attempt to improve the operation of the Sound Church application, I’ve run into issues with Core Data returning an error when I attempt to save an Item.
The error:
2011-07-09 16:57:36.670 Sound-Church[12292:207] Unresolved error Error Domain=NSCocoaErrorDomain Code=256 “The operation couldn’t be completed. (Cocoa error 256.)” UserInfo=0x4d62010 {NSFilePath=/Users/john/Library/Application Support/iPhone Simulator/4.3.2/Applications/BF78B117-48CA-48C7-A61E-29A452E2824A/Documents/Sound_Church.sqlite, NSUnderlyingException=error during SQL execution : constraint failed}, {
NSFilePath = “/Users/john/Library/Application Support/iPhone Simulator/4.3.2/Applications/BF78B117-48CA-48C7-A61E-29A452E2824A/Documents/Sound_Church.sqlite”;
NSUnderlyingException = “error during SQL execution : constraint failed”;
}
I see the error from this code:
- (void)saveContext
{
NSLog(@"Entering saveContext");
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil)
{
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
In searching the web, I found this article that talks about that very message, but it doesn’t seem to apply as apparently the writer is directly accessing the sqlite database, which I don’t do.
I also found this question and answer, which suggests a possible problem, but again, I don’t see it applying to me, as I use a NSFetchedResultsController to populate the UITableView and otherwise only fetch results to verify that the new Item is unique.
The code where I fetch results to check for an error:
- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if (!self.currentItemObject)
{
// We don't want to bother attempting to process all the header info.
return;
}
if ([elementName isEqualToString: kItemElementName])
{
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"guid == \"%@\"", currentItemObject.guid];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setPredicate: predicate];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Item"
inManagedObjectContext:self.context];
[request setEntity: entity];
NSError *error = [[[NSError alloc] init] autorelease];
NSMutableArray *items = [[context executeFetchRequest: request error: &error] mutableCopy];
if (!items)
{
// TODO: Need to do better error handling.
NSLog(@"Error fetching items. %@", [error localizedDescription]);
[items release];
return;
}
if (0 < [items count])
{
// This is a duplicate element, we don't want to save it.
[items release];
return;
}
[items release];
...
At this point, I haven’t resolved this issue, so I’m still looking for a solution.
In the process of digging through the code, I did stumble upon another problem. I found that the title of the podcasts seemed to always be the same as the summary. So I did some digging, and found that, in fact, I was not copying the data elements into the NSManagedObject. Dumb.. Since the objects (NSStrings in this case) are passed as pointers, when I would write the next string into the same NSMutableString, it overwrote the previous entry, so all elements of an object became the last thing I entered.
So that’s solved, but I’m going to have to do some more digging into the sqlite table to figure out the problem with the error.