Delete record from core data not working? - ios

I am working with core data, when I deleting record from DB it's not working.
Entity name : Entity
Attributes : id, date, title
- (void) getData {
NSFetchRequest * fetReq = [NSFetchRequest fetchRequestWithEntityName:#"Entity"];
NSError * fetchErrorObj;
NSArray *result = [self.ad.managedObjectContext executeFetchRequest:fetReq error:&fetchErrorObj];
NSLog(#"array count is %lu", result.count);
NSMutableArray *idArr = [[NSMutableArray alloc]init];
NSMutableArray *titleArr = [[NSMutableArray alloc]init];
NSMutableArray *dateArr = [[NSMutableArray alloc]init];
for (int i=0; i<result.count; i++) {
self.storedManagedObj = [result objectAtIndex:i];
[idArr addObject:[self.storedManagedObj valueForKey:#"id"]];
[titleArr addObject:[self.storedManagedObj valueForKey:#"title"]];
[dateArr addObject:[self.storedManagedObj valueForKey:#"date"]];
}
self.idArray = sidArr;
}
To delete record...
- (IBAction)deleteRecord:(UIButton *)sender {
NSNumber *value=[NSNumber numberWithInt:[[self.idArray objectAtIndex:0] intValue]];
NSLog(#"%#", [self.idArray objectAtIndex:0]);
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"Entity"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"id == %#", value];
NSLog(#"predicate :%#", predicate);
[request setPredicate:predicate];
NSLog(#"request :%#", request);
NSError *error = nil;
NSArray *result = [self.ad.managedObjectContext executeFetchRequest:request error:&error];
NSLog(#"result: %#", result);
if (!error && result.count > 0) {
for(NSManagedObject *managedObject in result){
NSLog(#"managedObject :%#", managedObject);
[self.ad.managedObjectContext deleteObject:managedObject];
}
//Save context to write to store
[self.ad.managedObjectContext save:nil];
}
}
I am getting result like this
predicate :id == 38
request : (entity: Entity; predicate: (id == 38); sortDescriptors: ((null)); type: NSManagedObjectResultType; )
result :(
)

The error is pretty clear. It states that you need to specify SortDescriptor to your FetchRequest
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"Entity"];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"<#Sort key#>"
ascending:YES];
request.sortDescriptors = #[sortDescriptor];
OR
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects: sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
Read : NSFetchRequest without sort descriptors
EDIT:
As OP isn't concerned about sorting the result in any specific order and the question lacks the description of entity and the only field that I can see in question is id updating my answer to use id in sort descriptor field
[[NSSortDescriptor alloc] initWithKey:#"id" ascending:YES];
EDIT 2:
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"Entity"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"id == %#", [self.idArray objectAtIndex:0]];
Issue in the code was :
NSNumber *value=[NSNumber numberWithInt:[[self.idArray objectAtIndex:0] intValue]];
OP was trying to create a NSNumber from an object in self.idArray using intValue which means idArray is a array of String and not NSNumber. That means id is saved as String in core data and not as NSNumber.
In predicate however OP was trying to pass NSNumber to compare with id. Since id is String and passed argument is NSNumber comparison was failing hence was not returning any objects.

Related

NSDictionary NSManagedObject

How to convert dictionary data to NSManagedObject data?
I used propertiesToFetch, and it returns dictionary data. But I want NSManagedObject data.
please guide me
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:catalogID, pageID, nil]];
[fetch setResultType:NSDictionaryResultType];
[fetch setReturnsDistinctResults : YES];
NSError* error = nil;
self.resultPageArray = [context executeFetchRequest:fetch error:&error];
When I changed the type to NSManagedObjectResultType, then I got non-distinct data. I read that while using propertiesToFetch it saves the data in dictionary format. But I want to get the distinct data and save it into the NSManagedObjects
Try This,
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:catalogID, pageID, nil]];
[fetch setResultType:NSManagedObjectResultType];
[fetch setReturnsDistinctResults : YES];
NSError* error = nil;
self.resultPageArray = [context executeFetchRequest:fetch error:&error];
My code :
NSError *error = nil;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"BookInfo"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setPropertiesToFetch:#[catalogID, pageID]];
[fetchRequest setPredicate: [NSPredicate predicateWithFormat:#"(bookId == %#)",strId]];
NSArray *fetchedItems = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if( fetchedItems.count > 0 ) {
BookInfo *bInfo = [fetchedItems lastObject];
NSLog(#"%#",bInfo.bookName);
}
I have solved the issue. I was fetching the data of NSManagedObjects. After that I saved that data to the other array without repetition. And return the new array.
self.resultPageArray = [context executeFetchRequest:fetch error:&error];
NSMutableArray *resultantFinalArr = [[NSMutableArray alloc] init];
for (int i = 0; i<resultPageArray.count; i++)
{
catalogPageDataModel *atIndexI = [resultPageArray objectAtIndex:i];
BOOL find = NO;
for (catalogPageDataModel* catalogPageDataModel in resultantFinalArr)
{
if (catalogPageDataModel.pageid.intValue == atIndexI.pageid.intValue)
{
find = YES;
break;
}
}
if (!find)
[resultantFinalArr addObject:atIndexI];
}
NSLog(#"result array count %lu",(unsigned long)resultantFinalArr.count);
NSLog (#"names: %#",resultantFinalArr);
return resultantFinalArr;

Cannot perform operation without a managed object context

I'm trying add items from core data query to nsmutablearray but I'm getting this error:
"Cannot perform operation without a managed object context"
Here is my code:
NSPredicate *productPredicate = [NSPredicate predicateWithFormat:#"TRUEPREDICATE"];
NSManagedObjectContext *moc = self.managedObjectContext;
NSEntityDescription *description = [ NSEntityDescription entityForName:#"Product" inManagedObjectContext:moc];
NSFetchRequest *request = [NSFetchRequest new];
request.predicate = productPredicate;
request.entity = description;
NSError *error = nil;
NSArray *results = [moc executeFetchRequest:request error:&error];
for (NSInteger i = 0; i < results.count; i++)
{
NSString *productName = [[results objectAtIndex:i] valueForKey:#"productName"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"productName == %#", productName];
NSArray *match = [_listOfProducts filteredArrayUsingPredicate:predicate];
if (match == 0)
{
[self.listOfProducts addObject:[results objectAtIndex:i]];
}
}
Where I'm getting the error is at the momento of adding the object to nsmutablearray:
[self.listOfProducts addObject:[results objectAtIndex:i]];
Any of you knows why I'm getting this error?, I'll really appreciate your help.

Exactly Matched NSString in Core Data iOS

I've my entity in CoreData named as myentity and an attribute named as myuniqueid and I want to run an SQL query as follows:
Select * from myentity where myuniqueid == 1000
How can I get my specified rows where it matches as in SQL query? such that I want to filter all rows where myuniqueid is 1000.
My Code:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *context = [self managedObjectContext];
if (context == nil) {}
else {
NSEntityDescription *entity = [NSEntityDescription entityForName:#"myentity" inManagedObjectContext:context];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"myuniqueid == 1000"];
[fetchRequest setPredicate:predicate];
[fetchRequest setEntity:entity];
NSArray *items = [context executeFetchRequest:fetchRequest error:nil];
for (int i=0; i<4; i++) {
NSManagedObject *mo = [items objectAtIndex:i]; // assuming that array is not empty
id value = [mo valueForKey:#"myuniqueid"];
NSLog(#"SENDER: %#",value);
}
}
Im getting error: 'Unable to generate SQL for predicate (myuniqueid == 1000) (problem on RHS)'
Try this predicate :
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"myentity"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"myuniqueid == %#", #(1000)];
NSArray *items = [[self managedObjectContext] executeFetchRequest:request error:nil];

Filter title from core data

I have an entity that has title title and amount. I would like to display the total value I have for each title in my entity.
You can pretty much dispense with fetch requests by leveraging KVC (Key-Value-Coding).
First fetch (or filter) with this predicate:
[NSPredicate predicateWithFormat:#"category = %#", #"Food"];
Then just sum up the result in one line:
NSNumber *sum = [result valueForKeyPath:#"#sum.amount"];
There is no need to fetch only certain attributes using NSDictionaryResultType - just fetch the normal NSManagedObjects (Core Data will optimize for you).
You use NSPredicate to filter your objects by category and then you can fetch only the values of a certain property e.g.:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
// Entity
NSEntityDescription *ent = [NSEntityDescription entityForName:#"Incoming" inManagedObjectContext:context];
[request setEntity:ent];
// Predicate
NSPredicate *pred = [NSPredicate predicateWithFormat:#"category MATCHES[cd] %#", #"FOOD"];
[request setPredicate:pred];
// Property fetch
[request setResultType:NSDictionaryResultType];
[request setReturnsDistinctResults:NO];
[request setPropertiesToFetch:#[#"Amount"]];
// Execute the fetch.
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
int total = 0;
if (objects) {
for(NSDictionary *dict in objects) {
NSString *key = dict.allKeys.lastObject;
total += [dict[key] intValue];
}
} else {
NSLog(#"Fetch error: %#", error.localizedDescription);
}
NSLog(#"Total: %i", total);
The following will get the categories and the sum in one fetch operation:
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Incoming"];
fetchRequest.resultType = NSDictionaryResultType;
NSExpression *sumExp = [NSExpression expressionWithFormat:#"sum:(amount)"];
NSExpressionDescription *sumED = [[NSExpressionDescription alloc] init];
sumED.name = #"sum";
sumED.expression = sumExp;
sumED.expressionResultType = NSDoubleAttributeType;
fetchRequest.propertiesToFetch = [#"title", sumED];
fetchRequest.propertiesToGroupBy = [#"title"];
NSArray *dictionaries = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
See the NSExpression documentation here.

Compare the contents of two arrays and finding the differences

I have two arrays, one is an array from a fetch request of core-data (array1), the other is from data that is being pulled from the web(array2). What I want to do is compare array1 to array2 and any items that are in array2 that are not in array1 need to be added to core-data.
The data I'm pulling from has id's associated with each person. When I create a new "person" entity I save this id with it as well. I'm not sure how to compare the arrays using the Person's id, or even how to access that within an array.
Here is the fetch request:
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
NSError *error = nil;
[fetch setEntity:[NSEntityDescription entityForName:#"Person" inManagedObjectContext:self.managedObjectContext]];
NSSortDescriptor *sorter = [NSSortDescriptor sortDescriptorWithKey:#"Pid" ascending:YES];
request.sortDescriptors = #[sorter];
NSArray *items = [self.managedObjectContext executeFetchRequest:request error:&error];
I have the fetch sorted in the same way array2 with the new data is sorted. I'm just not sure how to compare the two and then add the new items into core-data. Please help?
Update:
NSDictionary *qDict = [JSON objectForKey:#"person"];
NSArray *qArry = [JSON objectForKey:#"person"];
//Used to print the id's
_testArray = [NSMutableArray arrayWithArray:[qDict valueForKey:#"id"]];
for (NSNumber *numb in _testArray) {
NSLog(#"id = %#", numb);
}
NSError *error = nil;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Person"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"Pid IN %#", [qDict valueForKey:#"Pid"]];
[fetchRequest setPredicate:predicate];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"Pid" ascending:YES]]];
NSArray *items = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
NSLog(#"%d how many items from the fetch", items.count);
for (NSDictionary *qdt in qArry) {
NSUInteger currentIndex = 0;
Person *q = nil;
if ([items count] > currentIndex) {
q = [items objectAtIndex:currentIndex];
}
if ([q.Pid integerValue] == [[qdt objectForKey:#"id"] integerValue]) {
// Either update the object or just move on
}
else {
// Add the object to core data
q = [NSEntityDescription insertNewObjectForEntityForName:#"Person" inManagedObjectContext:self.managedObjectContext];
q.url = [qdt valueForKey:#"url"];
q.Pid = [qdt objectForKey:#"id"];
q.text = [qdt valueForKey:#"personText"];
NSError *error = nil;
[_managedObjectContext save:&error];
}
currentIndex++;
}
//[_managedObjectContext save:&error];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
UIAlertView *av = [[UIAlertView alloc] initWithTitle:#"Error retrieving data" message:#"Please try again" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[av show];
}];
First you can fetch the list of objects stored in your core data based on person's IDs that you retrieve from the web (idArray) and sort them based on the ID:
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Person"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"id IN %#", idArray];
[fetchRequest setPredicate:predicate];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"id" ascending:YES]]];
This will return you the list of objects that the id can also be found in the objects you retrieve from the web. Let us call this storedRecords array. Then you can do the following:
Set a counter,
Iterate over the downloadedArray (this is the array containing the objects retrieved from the web and it must be sorted by id too),
Use objectAtIndex in the storedRecords array,
Check the id of the storedManagedObject if it matches the id of the record object
if it does not match, it is a new object that you can save into core data. Otherwise, it is an existing object.
Increase the counter.
Here is an example:
int currentIndex = 0;
for (NSDictionary *record in downloadedArray) {
NSManagedObject *storedManagedObject = nil;
if ([storedRecords count] > currentIndex) {
storedManagedObject = [storedRecords objectAtIndex:currentIndex];
}
if ([[storedManagedObject valueForKey:#"id"] integerValue] == [[record valueForKey:#"id"] integerValue]) {
//this will be existing object in core data
//you can update the object if you want
} else {
//this will be new object that you can store into core data
}
currentIndex++;
}
This is similar to what is mentioned here:
http://www.raywenderlich.com/15916/how-to-synchronize-core-data-with-a-web-service-part-1
maybe you can do something like this:
NSMutableArray *webData = [NSMutableArray arrayWithObjects:#"object 1",#"object 2",#"object 3",#"object 4", nil];
NSMutableArray *coreData = [NSMutableArray arrayWithObjects:#"object 2",#"object 4", nil];
NSMutableArray *newData = [NSMutableArray arrayWithArray:webData];
[newData removeObjectsInArray:coreData];
//output "object 1", "object 3"
or if you have a custom NSObject inside the array and compare it with its primary key maybe you can do something like:
NSMutableArray *webData = [NSMutableArray arrayWithObjects:test1,test2,test3,test4, nil];
NSMutableArray *coreData = [NSMutableArray arrayWithObjects:test2,test3, nil];
__block NSMutableArray *newData = [NSMutableArray new];
[webData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
__block testObject *object = (testObject *)obj;
__block BOOL isExisting = NO;
[coreData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
testObject *innerObject = (testObject *)obj;
if(object._id == innerObject._id)
isExisting = YES;
}];
if(!isExisting)
[newData addObject:object];
}];
//output will be object 1 and object 4
Try this
NSMutableArray *array1 = [[NSMutableArray alloc] initWithObjects:#"a",#"a",#"a",#"d",#"b",#"b",#"c",#"a",#"c",nil];
NSMutableArray *array2 = [[NSMutableArray alloc] initWithObjects:[NSString stringWithFormat:#"%#",[array1 objectAtIndex:0]], nil];;
for(int i = 0;i<[array1 count];i++)
{
if ([array2 containsObject:[array1 objectAtIndex:i]]) {
NSLog(#"do nothing");
}
else{
[array2 addObject:[array1 objectAtIndex:i]];
NSLog(#"array2 is %#",array2);
}
NSLog(#"finally array2 is %#",array2);
}
array2 will be as { a,d,b,c }

Resources