Try fetch record from multiple entity - ios

i will try to work with multiple entity with core data.
core data in two entity name is Student and Detail both have inverse relationship. relationship name is Student -> Detail:detail Detail -> Student:student.
try to fetch record from both entity and display in table view. try multiple code but can't get result.
first code:
Detail *d;
NSMutableArray *arrObj = [[NSMutableArray alloc]init];
for(Student *tblObj in [d student]){
[arrObj addObject:tblObj];
}
NSLog(#"Your records related with tableA = %#",arrObj);
can't load data in array.
second code:
NSArray* fetchResults = [_mainContext executeFetchRequest:fetchRequest error:nil];
for (int i; i > 1; i++) {
Student *tableAObject = fetchResults[i];
NSString * itemcode = tableAObject.detail.email;
NSLog(#"%#",itemcode);
}
can't display record.
third way:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *aEntity = [NSEntityDescription entityForName:#"Student" inManagedObjectContext:_mainContext];
[fetchRequest setEntity:aEntity];
NSString *relationshipKeyPath = #"detail"; // Set this to the name of the relationship on "SP" that points to the "Code" objects;
NSArray *keyPaths = [NSArray arrayWithObject:relationshipKeyPath];
[fetchRequest setRelationshipKeyPathsForPrefetching:keyPaths];
NSMutableArray *arrObj = [[NSMutableArray alloc]init];
for(Student *spObj in arrObj)
{
NSLog(#"description is %#",spObj.name);
Detail *codObj = spObj.detail;
NSLog(#"it has value %#",codObj);
NSLog(#" unique name is %#",codObj.email);
}
Code for insert data in core dta:
- (IBAction)submitData:(id)sender {
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate manageObjectContext];
Student *student = (Student *)[NSEntityDescription insertNewObjectForEntityForName:#"Student" inManagedObjectContext:context];
student.name = _nameText.text;
student.number = _noText.text;
student.study = _studyText.text;
Detail *detail = (Detail *)[NSEntityDescription insertNewObjectForEntityForName:#"Detail" inManagedObjectContext:context];
detail.number = _noText.text;
detail.email = _emailText.text;
detail.address = _addressText.text;
detail.contact = _contactText.text;
student.detail = detail;
detail.student = student;
NSError *error = nil;
[context save:&error];
if (![context save:&error]) {
NSLog(#"error in adding data %#, %#", error, [error userInfo]);
abort();
}
}
if you need more details let me know. Thank you.

The first two ways you have tried won't work as there is no code that related to fetch the data from core data. In the third way problem is you are not executing your fetch request.
Following is the way to fetch data from core data.
NSFetchRequest *req = [[NSFetchRequest alloc] initWithEntityName:#"Student"];
NSError *error = nil;
NSArray *students = [context executeFetchRequest:req error:&error];
for (Student *stdObj in students)
{
//Student object
NSLog(#"Name %#",stdObj.name);
NSLog(#"Number %#",stdObj.number);
//Detail object related to student
Detail *detailObj = stdObj.detail;
NSLog(#"Email %#",detailObj.email);
NSLog(#"Address %#",detailObj.address);
}

Related

Fetching all the records inside a particular attribute in core data?

In this example i have an array named "nameArray" which holds five objects-{A,B,C,D,E}. In Core Data i have an entity named "Details" and an attribute "name". I have saved the "nameArray" inside the core database. After that i have used NSFetchRequest to fetch all the data stored inside "name" attribute. The code i have used is below:
_nameArray = [NSArray arrayWithObjects:#"A",#"B",#"C",#"D",#"E", nil];
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
Details *userDetails = [NSEntityDescription insertNewObjectForEntityForName:#"Details" inManagedObjectContext:appDelegate.persistentContainer.viewContext];
for (NSString*name1 in _nameArray)
{
userDetails.name = name1;
}
NSError *error;
[appDelegate.persistentContainer.viewContext save:&error];
if (error==nil)
{
NSLog(#"Data is saved");
}
else
{
NSLog(#"Data not saved and error is %#",error);
}
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Details"];
NSManagedObjectContext *context = [self manage]
NSArray *results = [appDelegate.persistentContainer.viewContext executeFetchRequest:request error:nil];
NSLog(#"The result array is %#",results);
if (results.count>0)
{
NSManagedObject *name1 = (NSManagedObject *)[results objectAtIndex:0];
NSLog(#"The name is %#",[name1 valueForKey:#"name"]);
}
The problem is that i am not able to fetch all the records stored inside the "name" attribute. The "results" array is giving only one object, i.e. the last object 'E' as output. I need to output all the data stored inside the "name" attribute. The "results" array output is below:-
The result array is (
" (entity: Details; id: 0xd000000000040000 ; data: )",
" (entity: Details; id: 0xd000000000080000 ; data: {\n name = E;\n number = 0;\n})"
)
You inserted one object into CoreData and keep updating that object. You need to move the line
Details *userDetails = [NSEntityDescription insertNewObjectForEntityForName:#"Details" inManagedObjectContext:appDelegate.persistentContainer.viewContext];
into the for loop as follows
for (NSString*name1 in _nameArray)
{
Details *userDetails = [NSEntityDescription insertNewObjectForEntityForName:#"Details" inManagedObjectContext:appDelegate.persistentContainer.viewContext];
userDetails.name = name1;
}
And if you want to see all the inserted objects
NSArray *results = [appDelegate.persistentContainer.viewContext executeFetchRequest:request error:nil];
if (results.count>0)
{
for (NSManagedObject*userDetails in results)
{
NSLog(#"The name is %#",[userDetails valueForKey:#"name"]);
}
}
You can make use of the following method to fetch all records for a particular entity.
In your case pass nil to predicate
+(NSArray*)getAllObjectsForEntityName:(NSString*)entityName WithPredicate:(NSPredicate*)predicate{
AppDelegate *appDel = (AppDelegate*)[UIApplication sharedApplication].delegate;
NSFetchRequest *request = [[NSFetchRequest alloc]initWithEntityName:entityName];
NSError *error = nil;
if(predicate)
[request setPredicate:predicate];
NSArray *results = [appDel.managedObjectContext executeFetchRequest:request error:&error];
if (error != nil) {
//Deal with failure
}
else {
//Deal with success
}
return results;
}
and to save data inside core data you have to update your code
_nameArray = [NSArray arrayWithObjects:#"A",#"B",#"C",#"D",#"E", nil];
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
for (NSString*name1 in _nameArray)
{
Details *userDetails = [NSEntityDescription insertNewObjectForEntityForName:#"Details" inManagedObjectContext:appDelegate.persistentContainer.viewContext];
userDetails.name = name1;
}

How to get single attribute Value of entity in Coredata?

I am having Entity Called EY_Appliances with Attributes applianceId ,applianceName,watts,amountPerWatts.Also i am Having Arrays like this:
Prefrence.h
#define APPLIANCENAME_ARRAY #[#"Fridge",#"Microwave",#"Mixie",#"Roti Maker",#"Coffee Machine",#"Dish Washer",#"Wet Grinder",#"Electric Stove",#"Ceiling Fan",#"TV",#"Table Fan",#"Tubelight",#"Bulb",#"AC",#"Vacuum Cleaner",#"CFL",#"LED",#"Washing Machine",#"Toaster",#"Room Heater",#"Iron",#"Motor",#"Water Heater",#"Inverter / UPS",#"Air Cooler",#"Steamer / Air Fryer",#"Hair Dryer",#"Laptop",#"PC",#"Tablet",#"Router / Modem",#"Home Theatre",#"Projector",#"PS3/PS4/XBOX"]
#define WATTS_ARRAY #[#"120",#"1000",#"700",#"30",#"167",#"810",#"180",#"150",#"75",#"120",#"75",#"40",#"60",#"1200",#"1400",#"20",#"6",#"300",#"1000",#"1600",#"1400",#"2400",#"1000",#"67",#"173",#"585",#"1026",#"15",#"150",#"4",#"4",#"17",#"240",#"10"]
DataAccessHandler.m
-(void)storeApplianceDetailsToEntity
{
NSManagedObjectContext *context = [self managedObjectContext];
for (int i=0; i<APPLIANCENAME_ARRAY.count; i++)
{
NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:#"EY_Appliances" inManagedObjectContext:context];
[object setValue: APPLIANCENAME_ARRAY[i] forKey:#"applianceId"];
[object setValue: APPLIANCENAME_ARRAY[i] forKey:#"applianceName"];
[object setValue: WATTS_ARRAY[i] forKey:#"watts"];
[object setValue: WATTS_ARRAY[i] forKey:#"amountPerWatts"];
}
NSError *error = nil;
if (![context save:&error])
{
NSLog(#"Saving Failed with error %#", error);
}
NSLog(#"entityValue==>%#",context);
}
-(NSArray *) fetchApplianceDetailsFromEntity:(NSString *) entityName
{
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest;
NSEntityDescription *entityDescription;
NSArray *array;
fetchRequest = [[NSFetchRequest alloc] init];
entityDescription = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entityDescription];
array = [managedObjectContext executeFetchRequest:fetchRequest error:nil];
NSLog(#"arr==>>%#",array);
return array;
}
ViewController.m
-(void)viewDidLoad
{
DataAccessHandler *dataAccess=[[DataAccessHandler alloc]init];
[dataAccess storeApplianceDetailsToEntity];
NSArray *applianceData = [dataAccess fetchApplianceDetailsFromEntity:#"EY_Appliances"];
//How to print the applianceName,If i write Like this applianceData.applianceName,it shows error…
}
1.How to print the applianceName?
2.How to set the applianceId primaryKey and store the value for applianceId 1 to 34?
NSDictionary *applianceData = [dataAccess fetchApplianceDetailsFromEntity:#"EY_Appliances"];
use keyword get back value
applianceData is an array, so you need to access it through an index
Your code just now is using the appliance name as ID - if all you need is an identifier, you can use your index i
The load returns everything into the array - if you only want to load part of the dataset, you need to add a fetch predicate in fetchApplianceDetailsFromEntity
[fetch setPredicate:[NSPredicate predicateWithFormat:#"(applianceId == %#)",idString]];

Populating an Array from Core Data in Xcode

I am trying to populate an NSArray with a collection of data I get from CoreData. But my array doesnt seem to be populating with the data. I have the following code to retrieve the data:
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]
initWithEntityName:#"WeightLog"];
self.contactarray = [[managedObjectContext executeFetchRequest:fetchRequest
error:nil] mutableCopy];
And I am using the following for loop to populate the NSArray with the data I collect from WeightLog for a particular field.
for (int i =0; i<=self.contactarray.count; i++) {
NSManagedObject *device = [self.contactarray objectAtIndex:i];
[titleNames addObject:device];
}
Just so you know contactarray is a property in my .h file of the following format:
#property (strong) NSMutableArray *contactarray;
Can you tell me where I am going wrong please, I am fairly new to iOS Development, if it doesn't show.
Thank you in advance
Initialise titleNames array before use. Try this,
titleNames = [[NSMutableArray alloc] init];
for (int i =0; i<=self.contactarray.count; i++) {
NSManagedObject *device = [self.contactarray objectAtIndex:i];
[titleNames addObject:device];
}
Just call this user-defined method. for ex -
self.titleNames = [self selectAllRowInEntity:#"WeightLog"];
-(NSArray *) selectAllRowInEntity:(NSString *) entityName
{
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fRequest;
NSEntityDescription *eDesc;
NSArray *arr;
fRequest = [[NSFetchRequest alloc] init];
eDesc = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
[fRequest setEntity:eDesc];
arr = [managedObjectContext executeFetchRequest:fRequest error:nil];
return arr;
}
This line here:
self.contactarray = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
This is a cardinal sin in Core Data - to not use the provided error parameters.
NSError *error;
self.contactarray = [[managedObjectContext executeFetchRequest:fetchRequest
&error] mutableCopy];
if (!self.contactArray) {
// Fetch Requests return a nil on error, in which case you should check the error.
NSLog(#"Error occurred: %#", error);
} else {
// do whatever you want with the array
}
Now run your code and look at the console and you might see the reason for the error.
Edited to add
Following a comment:
You should always check that the return of the method is nil before evaluating the error object. For Cocoa (and Cocoa-Touch) methods this is the only time that the error parameter is guaranteed to be valid.
This is taken from the Error Handling Programming Guide

CoreData insertNewObjectForEntityForName and executeFetchRequest return nil

I'll try to expose my problem, because is a bit complex.
I use Core Data and I have a problem with the data stored.
When I use this code:
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"ItemMessage"];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
NSMutableArray *values = [[NSMutableArray alloc] init];
if (error == nil) {
for (int i = 0; i<results.count; i++) {
NSLog(#"results %#",[results objectAtIndex:i]);
ItemMessage *itemMessage = [results objectAtIndex:i];
[values addObject:itemMessage];
}
ecc. the problem is that the value printed by NSLog is correct (the "results" contains something) but the itemMessage contains always 0 key/value pairs (it seems empty).
To understand what is the problem I went back and saw that in insertNewObjectForEntityForName I have also this problem, this is the code that I used when I save the messages data in Core Data:
for (id key in objectMessage) {
ItemMessage *itemmessage = [[ItemMessage alloc] init];
itemmessage.itemMessageId = [key objectForKey:#"itemMessageId"];
itemmessage.message = [key objectForKey:#"message"];
itemmessage.sender = [key objectForKey:#"sender"];
itemmessage.users = [key objectForKey:#"users"];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSManagedObject *newMessage;
newMessage = [NSEntityDescription insertNewObjectForEntityForName:#"ItemMessage" inManagedObjectContext:context];
[newMessage setValue: itemmessage.itemMessageId forKey:#"itemMessageId"];
[newMessage setValue: itemmessage.message forKey:#"message"];
[newMessage setValue: itemmessage.sender forKey:#"sender"];
[newMessage setValue: itemmessage.users forKey:#"users"];
[context save:&error];
if (error != nil) {
NSLog(#"Coredata error");
}
The problem is that newMessage after the insertNewObjectForEntityForName and the setValue contains also 0 key/value pairs.
Can you help me?
You don't seem to insert the new managed objects correctly into the context.
It should be:
for (id key in objectMessage) {
NSManagedObjectContext *context = [appDelegate managedObjectContext];
ItemMessage *itemmessage = (ItemMessage*)[NSEntityDescription insertNewObjectForEntityForName:#"ItemMessage"
inManagedObjectContext:context];
itemmessage.itemMessageId = [key objectForKey:#"itemMessageId"];
itemmessage.message = [key objectForKey:#"message"];
itemmessage.sender = [key objectForKey:#"sender"];
itemmessage.users = [key objectForKey:#"users"];
}
//save your inserts
To create a class file for your managed objects you could:
Go to your model file (xcdatamodeld) ->
select an entity ->
from the menu select:
Editor-> Create NSManagedObjectSubclass -> select the entities your like class files for.
Now you will have managed objects you could access with ease (NSManagedObject subclass) and benefit from CoreData features.
When you insert to manage object contest you have to call save: method, also the saving method should looks something like that:
newMessage = [NSEntityDescription insertNewObjectForEntityForName:#"ItemMessage" inManagedObjectContext:context];
// 2
newMessage.property1 = self.firstNameTextfield.text;
newMessage.property2 = self.lastNameTextfield.text;
if (![context save:&error]) {
NSLog(#"Error: %#", [error localizedDescription]);
}

fetch coredata relationship

I would like to know how to fetch the items from my coredata relation ship. I guess it should be a dictionary or arrays or something that gets returned so that you can have your one to many thing.
I am quite lost at this I know how to write/read single objects but this relationship stuff is abit confusing.
I think I have sucsessfully written a relationship to coredata however now I would like to be able to read it to see if I have it right.. I have started writing the method for this but have no idea what to actually do to get all of the information out.
this is the code i have so far.. for both read and write
- (void)writeFin:(NSArray *)recivedProjectData ItemsData:(NSArray *)itemsData {
// WRITE TO CORE DATA
NSManagedObjectContext *context = [self managedObjectContext];
for (NSDictionary *dict in recivedProjectData) {
project = [NSEntityDescription insertNewObjectForEntityForName:#"Project" inManagedObjectContext:context];
project.proNumber = [dict valueForKey:#"ProNumber"];
project.projectDescription = [dict valueForKey:#"Description"];
// project.items = [dict valueForKey:#""]; // this is the relationship for project
}
for (NSDictionary *dict in itemsData) {
items = [NSEntityDescription insertNewObjectForEntityForName:#"Items" inManagedObjectContext:context];
items.Number = [dict valueForKey:#"Number"];
items.Description = [dict valueForKey:#"Description"];
items.comment = [dict valueForKey:#"Comment"];
items.project = project; // this is the relationship for items
[project addItemsObject:items];
}
NSError *error = nil;
if (![__managedObjectContext save:&error]) {
NSLog(#"There was an error! %#", error);
}
else {
NSLog(#"created");
}
}
- (NSMutableArray *)readFin {
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error;
NSMutableArray *projectDictionaryArray = [[NSMutableArray alloc] init];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (ProjectList *projectList in fetchedObjects) {
NSMutableDictionary *tempProjectDictionaryArray = [[ NSMutableDictionary alloc] init];
[tempProjectDictionaryArray setObject:project.proNumber forKey:#"ProNumber"];
[tempProjectDictionaryArray setObject:project.description forKey:#"Description"];
[tempProjectDictionaryArray setObject:project.projectID forKey:#"ProjectID"];
[projectDictionaryArray addObject:tempProjectDictionaryArray];
}
return projectDictionaryArray;
}
So just o reiterate, I would like to know A, is my write method look okay? B, how do you fetch/read the relationship objects from core data.
any help would be greatly appreciated.
A relationship in Core Data isn't an object, its a property which happens to correspond to another object in your model rather than just being a dead end. You're already most of the way there as far as checking whether your relationships are ok as far as I can see -- what you need to do is add one more line in your projectList
[tempProjectDictionaryArray setObject: project.items forKey:#"items"];
the object that you will have added will be an NSSet. You can then check that things are as they should be with a loop like this after you've finished setting things up
NSSet itemsForProject = projectDictionaryArray[someIndex][#"items"]
for (Item* currItem in [itemsForProject allObjects]) {
//access some property of the current item to make sure you have the right ones -- \
description for example
NSLog(#"%#", item.description);
}

Resources