Not able to handle executeFetchRequest error - ios

My fetch request works fine and I get my fetched objects without any problems. What I want to do, is handle the error in case the entity doesn't exist. The problem is, I can't handle the error because the app crashes when I call executeFetechRequest: error: without any warnings.
My fetch looks like:
NSManagedObjectContext *context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"Info" inManagedObjectContext:context];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"infoID" ascending:YES]];
[request setReturnsObjectsAsFaults:NO];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"infoID like %#",[a substringFromIndex:13]];
request.predicate = predicate;
request.fetchBatchSize = 1;
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
if (error == nil) {
...
}
else {
//handle error
}
As I said, there's no problem as long as the entity exists, but I want to handle the error if it doesn't exist. Any idea? Cheers

You could ask the model if such entity is present:
NSArray *entities = managedObjectModel.entities;
BOOL canExecute=NO;
for(NSEntityDescription *ed in entities) {
// check if entity name is equal to the one you are looking for
if(found) {
canExecute=YES;
break;
}
}
if(canExecute) {
// execute your request and all the rest...
} else {
NSLog(#"Entity description not found");
}
if doesn't exist you don't execute the fetch reuest

Related

NSMergeConflict with newVersion = <deleted>

After spending a lot of hours with this error I come here to ask if somebody have some information about this error. I load two entities, a Parks entity and a GuidedTour entity. A Paks can be relatet to many GuidedTours but when I try to save it, the error raises:
Error Domain=NSCocoaErrorDomain Code=133020 "(null)" UserInfo={conflictList=(
"NSMergeConflict (0x17026afc0) for NSManagedObject (0x1740d94b0) with objectID '0xd000000000240002 ' with oldVersion = 0 and newVersion = and old cached row = {\n language = \"de_DE\";\n text = \"Apapapapapa"...}
I can't understand what is wrong, my Merge policy is: NSMergeByPropertyStoreTrumpMergePolicyType
And my code:
AppDelegate appDelegate = (AppDelegate)[[UIApplication sharedApplication] delegate];
self.context = [appDelegate managedObjectContext];
NSError *error = nil;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"GuidedTours" inManagedObjectContext:self.context ];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [self.context executeFetchRequest:fetchRequest error:&error];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"guided_tours_parks == NULL"];
fetchedObjects = [fetchedObjects filteredArrayUsingPredicate:predicate];
GuidedTours *tour = [fetchedObjects firstObject];
fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityPark = [NSEntityDescription entityForName:#"Parks" inManagedObjectContext:self.context ];
[fetchRequest setEntity:entityPark];
fetchedObjects = [self.context executeFetchRequest:fetchRequest error:&error];
predicate = [NSPredicate predicateWithFormat:#"name == %#",[jsonData objectForKey:#"Park ID"] ];
fetchedObjects = [fetchedObjects filteredArrayUsingPredicate:predicate];
Parks *park = [fetchedObjects firstObject];
[tour setGuided_tours_parks:park];
[park addParks_guided_toursObject:tour];
// Save the object to persistent store
if (![self.context save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}
Does somebody have any idea?
Thank you!
I had this exact same error, and in my case it occurred on inserts after attempting to perform an NSBatchDeleteRequest. The problem was that after performing the NSBatchDeleteRequest, I was not calling the [self.context reset] method.
As per a WWDC 2015 talk, batch updates/deletions circumvent the context and directly modify the persistent store file. Thus, if you do not call reset, your context will contain deleted objects which can cause the above merge conflict you experienced.
https://developer.apple.com/videos/play/wwdc2015/220/

Core Data was mutated while being enumerated

I've an annoying problem with Core Data. My app need to get contacts from iPhone and save it in my database. I'm trying to do that in background thread.
I use above code for that:
[self performSelectorInBackground:#selector(fetchingContact) withObject:nil];
-(void)fetchingContact{
// Some Code
for (int i = 0; i < nPeople; i++)
{
//Some Code
NSManagedObjectContext *context = [APP_DELEGATE managedObjectContext];
ABRecordID recordID = ABRecordGetRecordID(person);
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Contact" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"(contactId = '%d')",recordID]];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
//crash
NSArray *contactObjArray = [context executeFetchRequest:fetchRequest error:&error];
//crash
if (error) {}
Contact *contacts;
if (contactObjArray.count == 0) {
contacts = [NSEntityDescription insertNewObjectForEntityForName:#"Contact" inManagedObjectContext:context];
}else {
contacts = [contactObjArray objectAtIndex:0];
}
//Some Code
}
}
In AppDelegate:
- (NSManagedObjectContext *)managedObjectContext
{
NSLog(#"managedObjectContext");
// Returns ;the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
}
_managedObjectContext = [[NSManagedObjectContext alloc]initWithConcurrencyType: NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
return _managedObjectContext;
}
Here I try to save in my Core Data but it crash with error :
* Terminating app due to uncaught exception 'NSGenericException', reason: '* Collection <__NSCFSet: 0x15fad880> was mutated while being enumerated.'` at this line:
NSArray *contactObjArray = [context executeFetchRequest:fetchRequest error:&error];
I search already online, I found a lot of things but nothing helps me. When I run that, there is no place where Core Data is changed, or Contact entity. That does this error very strange.
If I run it in main thread I get no errors/ no crash, but if the app is quit in that time (while is executed) I lose all content from Contact
Please, any help. Tell me if I need to provide more information.
This error happen when you are modifying core data while you try to get them.
That also could be cause of the loop you're doing, you are inserting a new object in coredata without saving before you do an other retrieve. Try saving your managedobjectcontext :
favorite
I have an annoying problem with Core Data. My app need to get contacts from iPhone and save it in my database. I'am trying to do that in background thread.
I use above code for that:
[self performSelectorInBackground:#selector(fetchingContact) withObject:nil];
-(void)fetchingContact{
// Some Code
for (int i = 0; i < nPeople; i++)
{
//Some Code
NSManagedObjectContext *context = [APP_DELEGATE managedObjectContext];
ABRecordID recordID = ABRecordGetRecordID(person);
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Contact" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"(contactId = '%d')",recordID]];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
NSArray *contactObjArray = [context executeFetchRequest:fetchRequest error:&error];
if (error) {}
Contact *contacts;
if (contactObjArray.count == 0) {
contacts = [NSEntityDescription insertNewObjectForEntityForName:#"Contact" inManagedObjectContext:context];
[context save:&error];
}else {
contacts = [contactObjArray objectAtIndex:0];
}
//Some Code
}
}
If that doesn't solve your problem, maybe check if your method is called multiple times.

Saving coredata on background thread causes fetching into a deadlock and crash

I'm saving coredata in a background method (parent-child) but fetching is done on main thread. So i'm getting a deadlock in the fetch method and sometimes app crashed. Is there anything wrong i'm doing? How can i improve both save and fetch without affect main thread? I have read many documents but none of them explaining me how to use both in a project. If this is a wrong question please guide me to proper solution and let me know my mistakes please.
-(ThreadInfo *)retrieveSolicitationInfoForThreadID:(NSString*)inThreadID;
{
NSString *loginUser=[[NSUserDefaults standardUserDefaults] valueForKey:#"currentUser"];
AppDelegate *sharedDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [sharedDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setReturnsObjectsAsFaults:NO];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"ThreadInfo"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *userPredicate = [NSPredicate predicateWithFormat:#"userEmail == %#",loginUser];
NSPredicate *threadPredicate = [NSPredicate predicateWithFormat:#"threadID == %#",inThreadID];
NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates: #[userPredicate, threadPredicate]];
[fetchRequest setPredicate:compoundPredicate];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:nil];
if(fetchedObjects.count!=0)
{
ThreadInfo *threadInfo=[fetchedObjects objectAtIndex:0];
return threadInfo;
}
return nil;
}
SAVE
-(void)updateThreadEntityWithSyncDetails:(NSMutableDictionary *)inDictionary
{
NSString *loginUser=[[NSUserDefaults standardUserDefaults] valueForKey:#"currentUser"];
AppDelegate *sharedDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [sharedDelegate managedObjectContext];
// NSManagedObjectContext *writerContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
// [writerContext setPersistentStoreCoordinator:[sharedDelegate persistentStoreCoordinator]];
// create main thread MOC
context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
context.parentContext = writerContext;
NSManagedObjectContext *contextforThread = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
contextforThread.parentContext = context;
[contextforThread performBlock:^{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setReturnsObjectsAsFaults:NO];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"ThreadInfo"
inManagedObjectContext:contextforThread];
[fetchRequest setEntity:entity];
NSPredicate *userPredicate = [NSPredicate predicateWithFormat:#"userEmail == %#",loginUser];
NSPredicate *threadPredicate = [NSPredicate predicateWithFormat:#"threadID == %#",[inDictionary valueForKey:#"thread"]];
NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates: #[userPredicate, threadPredicate]];
[fetchRequest setPredicate:compoundPredicate];
NSArray *fetchedObjects = [contextforThread executeFetchRequest:fetchRequest error:nil];
for (ThreadInfo *threadInfo in fetchedObjects)
{
if([[inDictionary allKeys] containsObject:#"userEmail"])
{
if([inDictionary valueForKey:#"userEmail"]!=[NSNull null])
{
threadInfo.userEmail=[inDictionary valueForKey:#"userEmail"];
}
}
if([[inDictionary allKeys] containsObject:#"badgeValue"])
{
if([inDictionary valueForKey:#"badgeValue"]!=[NSNull null])
{
threadInfo.badgeValue=[inDictionary valueForKey:#"badgeValue"];
}
}
if([[inDictionary allKeys] containsObject:#"choice4Percentage"])
{
if([inDictionary valueForKey:#"choice4Percentage"]!=[NSNull null])
{
threadInfo.choice4Percentage=[inDictionary valueForKey:#"choice4Percentage"];
}
}
if([[inDictionary allKeys] containsObject:#"choice5Percentage"])
{
if([inDictionary valueForKey:#"choice5Percentage"]!=[NSNull null])
{
threadInfo.choice5Percentage=[inDictionary valueForKey:#"choice5Percentage"];
}
}
}
NSError *error;
if(![context save:&error]) {
NSLog(#"Child error : %#",error);
}
[context performBlock:^{
NSError *error;
if(![context save:&error]) {
NSLog(#"%#",error);
}
}];
}];
}
The issue is your fetch. You are fetching two strings against what I am guessing is a large number of entities in your store. Your fetch performance is 100% of your issue.
A) You should not be doing string compares if it can be avoided
B) You should not be doing TWO string compares ever
Your data model needs to be refactored. Doing two string compares against a table that has a large number of entities is going to perform badly no matter what.
Update
Your data structure is bad. I don't know how many ways I can say that. Ideally you want an integer or other number structure as your unique identifier.
Since you are not telling me/us how many entities you are dealing with I can only guess you have a large number. How man results are expected? One? Or Many? Is this a unique constraint that you are working against? If not, why isn't there a unique constraint coming from your server? If it is a unique constraint why haven't you limited the fetch size like I suggested?
You are not giving me any information but hoping I can magically fix your problem.
Reducing it to one string is something you can try but you are asking me how your data is going to behave. TEST it. You have instruments and you have the data. Change things and compare the results.
Strings are expensive. They always have been and always will be.
Update
Since it is a unique constraint you can do yourself a large favor and change your code just a bit:
- (ThreadInfo *)retrieveSolicitationInfoForThreadID:(NSString*)inThreadID;
{
NSString *loginUser = [[NSUserDefaults standardUserDefaults] valueForKey:#"currentUser"];
AppDelegate *sharedDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [sharedDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"ThreadInfo"];
[fetchRequest setReturnsObjectsAsFaults:NO];
//Since there is every only one tell SQL to stop looking after one
[fetchRequest setFetchBatchSize:1];
/* Change these to your single constraint
NSPredicate *userPredicate = [NSPredicate predicateWithFormat:#"userEmail == %#",loginUser];
NSPredicate *threadPredicate = [NSPredicate predicateWithFormat:#"threadID == %#",inThreadID];
NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates: #[userPredicate, threadPredicate]];
[fetchRequest setPredicate:compoundPredicate];
*/
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(#"Error fetching: %#\n%#", [error localizedDescription], [error userInfo]);
abort();
}
return [fetchedObjects lastObject];
}
Setting the fetch limit will cause the store to stop looking after the first match which will reduce the fetch time. Moving it to a single string also reduces the fetch time.
In the future, avoid strings in this situation. Doing an integer primary key is incredibly fast and will avoid this performance problem entirely.
facing to problems such as coreData and multiplyThreads,you should add the following code in the corresponding method:
[[NSNotificationCenter defaultCenter] addObserver: cdm.managedObjectContext selector: #selector(mergeChangesFromContextDidSaveNotification:) name:NSManagedObjectContextDidSaveNotification object: nil];
Then the coreData changes at a thread,it will instantly update it in another thread where the coreData is being used.
Wish the answer will help you!

Core-Data executeFetchRequest freezes App in a background thread

I have a saveMOC which is the direct parent of a mainMOC, and I need for online fetch another tmpMOC in order not to block my UI whilst fetching a ton of records from the Internet.
My app freezes.
I could narrow it to this very point:
fetchedItems = [tmpMOC executeFetchRequest:fetchRequest error:&error];
I tried to enclose this within dispatch_sync, [moc.parentcontext.parentcontext.persistentStoreCoordinator lock/unlock], [whatevermoc performBlockAndWait]...
I also try to fetch the _mainMOC... No way...
I understand that executeFetchRequestis not thread safe, so, how do I lock whatever I need to lock to get sure I am not inserting a double?
Anybody could help?
UPDATE (1)
_saveMOC instantiation in AppDelegate:
- (NSManagedObjectContext *)managedObjectContext
{
if (_mainMOC != nil) {
return _mainMOC;
}
if (_saveMOC == nil) {
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_saveMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_saveMOC setPersistentStoreCoordinator:coordinator];
[_saveMOC setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
}
}
if (_mainMOC == nil) {
_mainMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainMOC setParentContext:_saveMOC];
[_mainMOC setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(saveContextChanges:) name:NSManagedObjectContextDidSaveNotification object:_mainMOC];
temporaryMOCcreation in MainViewController:
NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
temporaryContext.parentContext = _mainMOC;
[temporaryContext performBlock:^{ //AndWait
NSError *error=nil;
Feed *feed=(Feed *)[temporaryContext existingObjectWithID:feedID error:&error];
//...
[RSSParser parseRSSFeedForRequest:req success:^(NSArray *feedItems)
{
NSLog(#"[MasterViewController::fetchPosts] inserting %d Posts.../OK", (int)[feedItems count]);
feed.valid = [NSNumber numberWithBool:YES];
for(RSSItem *i in feedItems)
{
[self createPostInFeed:feed withTitle:i.title withContent:(i.content?i.content:i.itemDescription) withURL:[i.link absoluteString] withDate:(i.pubDate?i.pubDate:[NSDate date]) inMOC:temporaryContext];
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"NewPostsFetched" object:f];
Then the freeze happens in createPostInFeed:
// #synchronized(fetchRequest) { // THIS DOESN'T CHANGE ANYTHING
// [moc.persistentStoreCoordinator lock]; // THIS NEITHER
NSArray *fetchedItems;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *ent = [NSEntityDescription entityForName:#"Post" inManagedObjectContext:moc];
fetchRequest.entity = ent;
fetchRequest.propertiesToFetch = [NSArray arrayWithObjects:#"title", #"url", #"feed.name", nil];
[fetchRequest setResultType:NSDictionaryResultType];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"title == %# AND url == %# AND feed.rss == %#", title, url, feed.rss];
NSError *error = nil;
fetchedItems = [moc executeFetchRequest:fetchRequest error:&error]; // FREEZES HERE
// [moc.persistentStoreCoordinator unlock]; // THIS DOESN'T CHANGE ANYTHING
// } // Synchronized neither...
Update (2):
Here's what the Time Profiler sees.
Update (3):
Block edited:
NSUInteger fetchedItems;
NSString *feedRSS=feed.rss;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *ent = [NSEntityDescription entityForName:#"Post" inManagedObjectContext:moc];
fetchRequest.entity = ent;
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"title == %# AND url == %# AND feed.rss == %#", title, url, feedRSS];
NSLog(#"MainViewController::createPostInFeed> Before fetchRequest for %# (%#)", title, url);
NSError *error = nil;
fetchedItems = [moc countForFetchRequest:fetchRequest error:&error];
NSLog(#"MainViewController::createPostInFeed> After fetchRequest for %# (%#)", title, url); // THIS NSLOGGING NEVER HAPPENS
Update (4):
New profiler pic with call tree inverted.
What is your goal with createPostInFeed? You show that you are doing a fetch but what do you do with that fetch? Is this a "insert or update" check? or is it just a "insert or skip" test?
Any fetch is going to lock the NSPersistentStoreCoordinator and cause your application to potentially lock up while the fetch is being performed. There are ways to mitigate that:
Run Instruments
Make your fetches more efficient
If you don't need objects (in a insert or skip test) then do a count instead
Fetch on a background queue and make sure your main MOC has all the objects it needs to avoid a lock
What does your instruments profile show you?
What does createPostInFeed do with the results of that fetch?

array count returned from NSFetchRequest is wrong

I'm using Core Data to cache data, here is my code to insert object:
//data array count is 15
for (NSDictionary *dictionary in dataArray)
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"CacheData" inManagedObjectContext:context];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"title LIKE '%#'",dictionary[#"title"]];
[request setPredicate:predicate];
NSArray *fetchArray = [context executeFetchRequest:request error:NULL];
if ([fetchArray count] == 0)
{
CacheData *cacheData = [NSEntityDescription insertNewObjectForEntityForName:#"CacheData" inManagedObjectContext:context];
[cacheData setTitle:dictionary[#"title"]];
[cacheData setLink:dictionary[#"link"]];
[cacheData setPublishDate:dictionary[#"pubDate"]];
NSError *insertError = nil;
if (![context save:&insertError])
{
return NO;
}
}
}
The count of dataArray is 15, so I should insert 15 items to Core Data.
But once I used NSFetchRequest to fetch items, the array count returned added 1, and become 16, and fetch items again, it added 1 to 17 again:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"CacheData" inManagedObjectContext:[[CacheDataManagement sharedInstance] managedObjectContext]];
[request setEntity:entity];
NSArray *fetchArray = [[[CacheDataManagement sharedInstance] managedObjectContext] executeFetchRequest:request error:NULL];
for (CacheData *data in fetchArray) {
NSLog(#"fetch:%#",[data title]);
}
NSLog(#"%ld",[fetchArray count]); //fetch array count is 16
Something wrong with my code ?
Update
Changed if ([fetchArray count] != 0) { … } to if ([fetchArray count] == 0) { … }
Since the problem it's not quite clear to me (I would like to have more details), I'll try to give you some hints.
First, the save should be done outside the for loop (In addition it's not correct to do a return within it).
// for in loop here
NSError *insertError = nil;
if (![context save:&insertError]) {
NSLog("%#", insertError);
return NO; // do it if the method you are running in returns a bool
}
Second, to check for duplicated you should rely on a GUID but if don't have it the predicate should look like the following.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"title == %#",dictionary[#"title"]];
Third, also the execute for executeFetchRequest:error: should be replace with countForFetchRequest:error: since you don't need to return the objects but only a count. According to Apple doc, it
Returns the number of objects a given fetch request would have
returned if it had been passed to executeFetchRequest:error:.
Finally, in the for loop you are executing a request each time. My suggestion is to move execute a request before the loop and then checking for results within it. This according to Implementing Find-or-Create Efficiently. In this case, the pattern will enforce you to have a GUID for you entity.
Obviously, these are just hints. The real way to find the problem is to debug. In addition, I will perform tests starting from a fresh environment, i.e. the app has been deleted from the simulator or device.
In your code [fetchArray count] != 0 checks the inserting data is already exists. Try changing it like
if ([fetchArray count] == 0)
{
CacheData *cacheData = [NSEntityDescription insertNewObjectForEntityForName:#"CacheData" inManagedObjectContext:context];
[cacheData setTitle:dictionary[#"title"]];
[cacheData setLink:dictionary[#"link"]];
[cacheData setPublishDate:dictionary[#"pubDate"]];
NSError *insertError = nil;
if (![context save:&insertError])
{
return NO;
}
}

Resources