Get all entities from Model.xcdatamodeld - ios

In my project I am using MagicalRecord framework (implementation of active record pattern for Core Data on iOS). How can I retrieve all existing ENTITIES from my .xcdatamodeld file? I have to iterate though all entities (classes that inherit from managed object in my project) to truncate stored data.
I have only default configuration set in my model file. So for the following data model:
My code that show how it should look like:
NSArray *myEntities = // Retrive my entities.
foreach (Class *c in myEntities) {
[c MR_truncateAll];
}

Okey I have found the solution over here. The answer is pretty simple:
NSArray *allEntities = [[NSManagedObjectModel MR_defaultManagedObjectModel] entities];
for (NSManagedObject *mo in allEntities) {
[[mo class] MR_truncateAll];
}

Related

Insert JSON array into the Core Data entities

I have a JSON returned by REST API to my already existing app that I am trying to fix. I am fairly new to objective C.
[
{
"Activities":"
[
{
"activityid":845,
"activityname":"Registration and networking breakfast",
"actvitydesc":"Registration and networking breakfast",
},
{
"activityid":846,
"activityname":"Plenary session: The Workforce Tsunami",
"actvitydesc":"It's Time to Rethink Talent
}
}
]
There is a core data entity Activity in my app, which contains the following attributes
Activityid activityname activitydesc
How can I insert the JSON data inside my core data entity? Is there any need to create model class to do that? Can I insert my json data directly into core data without creating model objects?
If you already have the entity called Activity you can use the NSManagedObject class to set the value for an Attribute. Try this
NSManagedObject *managedObject = [NSEntityDescription insertNewObjectForEntityForName:#"Activity" inManagedObjectContext:_managedObjectContext];
[managedObject setValue:[NSNumber numberWithInteger:4711] forKey:#"activityid"];
and so on...
You can also create the class by the Classgenerator of CoreData in XCode 8 there are multiple ways. Defaultly the class is generated automatically since XCode 8. If you don't like this you can disable it and generate the class manually. Just go to the CoreData Model --> Editor --> Create NSManagedObject Subclass. Note you have to deactivate the automatic code generation before. If you don't do that, you will become errors while building the project.
If the name of the JSON Attribute is equal to the name of the CoreData Attribute you can also loop over the Dictionary like this:
NSArray *wrapper = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:nil];
for(NSDictionary *dict in wrapper){
NSArray *activities = [dict objectForKey:#"Activities"];
for(NSDictionary *activity in activities){
NSManagedObject *managedObject = [NSEntityDescription insertNewObjectForEntityForName:#"Activity" inManagedObjectContext:_managedObjectContext];
// [managedObject setValue:[NSNumber numberWithInteger:4711] forKey:#"activityid"];
for(NSString *attributeName in activity)
[managedObject setValue:[activity objectForKey:attributeName] forKey:attributeName];
}
}
Hope that helps you...
To insert anything to core data you need to generate models. Create core data model editor (if you don't have one) and add Entities. There is lots of tutorials on the web how to do it.

How to save data in two NSMutableArray into a single entity using magical record

I'm fetching code & desc from web by calling an API. Then loading it into tableView and based on multiple selection I'm saving the selected values into two arrays i.e. selectedCode and selectedCodeDesc. My Entity is:
So I want to [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error){ but don't know how. I know this much:
- (IBAction)confirmPressed:(id)sender {
NSLog(#"Selected Are: %# - %#",selectedDX,selectedDesc);
for (NSString *code in selectedDX) {
if (!_dxToAddEdit) {
self.dxToAddEdit = [MainCode MR_createEntity];
}
[self.dxToAddEdit setCode:code];
[self.dxToAddEdit setCodeDescription:#""]; //what to give here
[self.dxToAddEdit setSuperBill:_forSuperBill];
}
//after this I'm calling the saveToPersistent
So what to give at setCodeDescription?
If I understood correctly and based on your description and example of code you can do the following:
NSManagedObjectContext *defaultContext = [NSManagedObjectContext MR_defaultContext];
// Sorry, I renamed selectedCode to selectedCodes and selectedCodeDesc to selectedCodeDescriptions for readability.
// Not sure whether selectedDX is actually selectedCodes.
for (NSInteger i=0; i<selectedCodes.count; ++i) {
NSString *code = selectedCodes[i];
NSString *description = selectedCodeDescriptions[i];
Diagnoses *newDiagnose = [Diagnoses MR_createEntityInContext:defaultContext];
newDiagnose.code = code;
newDiagnose.codeDescription = description;
newDiagnose.superBill = _forSuperBill;
}
[defaultContext MR_saveToPersistentStoreAndWait];
Actually, I would not save the response into two separated arrays. Because of:
Your code becomes difficult to read
Imagine that the model will change and instead of two properties it will contain 4. You will have to create additional arrays.
I would recommend you to parse the response directly into the managed objects. Of course, you may not save them into persistent storage just populate your table view.
I highly recommend you to read these tutorials about Core Data. It will give you insight how to work with Magical Record library. Although, the library simplifies a lot of work it would be better to know what is under the hood ;]

iOS: core data to many relationship

I have a doubt how to manage a "to many relationship" in core data.
In my example I have the main identity 'Struct' that have a "to many relationship" with another identity called 'Id_loc'
Then, I have this object in a JSON file that is a Struct identity:
{"id":"s1",
"n":"Name Struct",
"id_loc":["l1","l2"]} //id_loc can contain many element
when I parse this object I have id_loc as an array.
Inside Struct class I have two methods:
- (void)addLocObject:(Id_loc *)value;
- (void)addLoc:(NSSet *)values;
then I do this to store id_loc array inside:
Struct *struct = [NSEntityDescription insertNewObjectForEntityForName:#"Struct" inManagedObjectContext:context];
NSArray *array_loc = [element objectForKey:#"id_loc"];
NSSet *set = [NSSet setWithArray:array_loc];
[struct addLoc:set];
Is it a right way?
Is it not necessary to call this?
Id_loc *loc = [NSEntityDescription insertNewObjectForEntityForName:#"Id_loc" inManagedObjectContext:context];
EDIT
Is it the right answer?
Struct *struct = [NSEntityDescription insertNewObjectForEntityForName:#"Struct" inManagedObjectContext:context];
NSArray *array_loc = [element objectForKey:#"id_loc"];
for (id loc in array_loc){
Id_loc *loc = [NSEntityDescription insertNewObjectForEntityForName:#"Id_loc" inManagedObjectContext:context];
loc.ident = loc;
[struct addLocObject:loc];
}
You cannot really save an NSSet into the CoreData just like that. NSSet contains other CoreData entities only which are related to your main object.
To save an array with data you need to use NSData property and use NSKeyedArchiver to archive your NSArray with NSStrings.
However even it's simplest solution there are some limitations. For example you won't be able to use and predicates on those properties. Therefore I would recommend to make another entity which is "Location" and create a location objects based on those "l1", "l2" values.
Yes you use addLocObject: or if you want to add multiple ones you use - (void)addLoc:(NSSet *)values; But you have to create those objects - create them in core data withing your context and than add it to main object.
Probably if you have ID you want also to select first existing locations and create them only if the don't exist.

One to many relationship: not able to save

I am trying to create a one to many relationship with some data I have.
I have a single Project and many items, I am trying to set up the controller to save them but this is the first time I have ever used a one to many relationship and my head is about to explode.
This is what my save method looks like
- (void)writeProj:(NSArray *)recivedProData ItemsData:(NSArray *)itemsData {
// WRITE TO CORE DATA
NSManagedObjectContext *context = [self managedObjectContext];
for (NSDictionary *dict in recivedProData) {
Project *project = [NSEntityDescription insertNewObjectForEntityForName:#"Project" inManagedObjectContext:self.managedObjectContext];
project.projectNumber = [dict valueForKey:#"ProjectNumber"];
project.projectDescription = [dict valueForKey:#"Description"];
// project.items = [dict valueForKey:#""]; // this is the relationship for project
}
for (NSDictionary *dict in itemsData) {
Items *items = [NSEntityDescription insertNewObjectForEntityForName:#"Items" inManagedObjectContext:self.managedObjectContext];
items.description = [dict valueForKey:#"Description"];
items.area = [dict valueForKey:#"Area"];
items.stage = [dict valueForKey:#"Stage"];
// items.project = [dict valueForKey:#""]; // this is the relationship for items
}
NSError *error = nil;
if (![__managedObjectContext save:&error]) {
NSLog(#"There was an error! %#", error);
}
else {
NSLog(#"created");
}
[Project addItemsObject:items];
[__managedObjectContext saveOnSuccess:^{
NSLog(#"You created a relationship");
} onFailure:^(NSError *error) {
NSLog(#"There was an error! %#", error);
}];
}
So I have one Project and many Items, I just dont know how to set up the keyfields so that they save into core data as one project and many items.
So hopefully my code is making sense. If someone could just help me figure out how to save it properly that would be greatly appreciated.
Just set items.project to be equal to the project NSManagedObject you just made
items.project = project;
EDIT: if you have only one project, you should move the Project* project declaration outside of the recivedProData for loop -- you are making one project for every dictionary, and you say you only have one project ever. That entire block of code makes no sense if you have only one project though -- why do you have an array of Project data, and not just one dictionary?
I want to discuss your Core Data model, the one you configured using the Core Data GUI editor. I'm curious about the plurality of the entity named "Items" from the following line of code:
Items *items = [NSEntityDescription insertNewObjectForEntityForName:#"Items" inManagedObjectContext:self.managedObjectContext];
Maybe it's just a matter of semantics. It's possible, however, that the plurality of that entity name indicates a problem in your Core Data model. I'll try to explain, but this is pretty abstract stuff.
Although an entity may have a relationship that represents a collection of things, the entity itself is not really a collection of things; the entity is always a single thing in the model and should be treated as such in your code (and in your naming schemes).
Here's how I would describe your model in words:
The Project entity is a single thing with a relationship called items. The items relationship is a collection (a set) of Item entities (i.e., a one-to-many relationship). But each Item entity is a single thing.
Does your model in the GUI editor reflect this description?

How to save more than one people in an Entity (CoreData)

I have an entity which looks like this:
Entityname = Country
with the attributes "city" and "person".
Country *country = [NSEntityDescription insertNewObjectForEntityForName:#"Country" inManagedObjectContext:context];
country.city = #"New York";
country.person = #"Doug";
country.person = #"Carry";
country.person = #"Arthur";
I want to save more then one people in that City.
I am using the code posted above, but only the last person is saved.
How I can save more then one people in CoreData?
Hope you can help me.
An approach for solving your problem would be:
Create 3 Entities: Country, City and Person
Setup the properties for your entities (e.g. Country.name, City.name, Person.name etc) using the graphical tool of XCode
Setup the relations between your Entities. You need a one-to-many from Country -> City [call it cities] and a one-to-many from City -> Person [call it persons] (See Apple's documentation regarding this subject). Keep in mind that you will need to set the inverse relations as well.
That's where all the fun begins... Choose Editor > Create NSManagedObject subclass. Xcode then will generate the files based on your model. Now if you look at the header files, you should see among the generated methods something similar to this:
...
- (void)addPersonObject:(Person *)value;
- (void)removePersonObject:(Person *)value;
- (void)addPersons:(NSSet *)value;
- (void)removePersons:(NSSet *)value;
...
From this point is quite obvious to figure out how to add multiple objects :)
I know that all this may seem hard at first but once you get yourself into this you will really be able to manage complex object graphs easy and efficiently.
I hope that this information will set you on the right track!
You will need to create an array with all the people you need to save to the core data model.
Try this code. Hope this will help you
yourArray = [[NSMutableArray alloc]initWIthObjects:#"Doug",#"Carry",#"Arthur"];
for(int i = 0; i < [yourArray count]; i++)
{
NSManagedObjectContext *context = [self managedObjectContext];
countryObject=[NSEntityDescription
insertNewObjectForEntityForName:#"Country"
inManagedObjectContext:context];
countryObject.city = #"New york";
countryObject.people = [NSString stringWithFormat:#"%#",[yourArray objectAtIndex:i]];
NSError *error;
if (![context save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
}
UPDATE:
AFTER YOU EXPLAINED THAT YOU DONT NEED THREE DIFFERENT INSTANCES, then
This can be done by creating a separate entity for City and People, then make a relationship between them as to-many relationship. So that you can achieve like that.

Resources