I'm trying to create a workout logging application using Swift. I have two entities, a "Workout" and "Lift". The "Lift" entity is supposed to be the child of the "Workout".
Whenever I create a new lift, I want it to be associated with that workout. Right now, my application will show every lift created regardless of the workout.
Here's an idea of my current Core Data model.
Entity: Workout
Attributes:
lifts, name, numOfLifts
Entity: Lift
Attributes:
liftName, sets, numOfSets
Looking through examples on SO, it seems like I need something where the lifts attribute of the workout class points to the lift entity. The problem was I couldn't find any examples using Swift.
Any help is appreciated, I can post code if needed or screenshots.
Have you setup a relationship between the Workout and Lift entities in XCode. If each Workout will have only one Lift then use One-to-One, otherwise if each Workout has many Lifts then use One-to-Many.
Once the link is established you just tell the new Lift Entity (at the point when you create it) which Workout it should be connected to.
See this thread for more information:
Saving CoreData to-many relationships in Swift
Related
I'm trying to write an iOS application that tracks how much weight your lifting at the gym but I'm struggling to create my Core Data schema. At the moment i have an Exercise Entity that stores info about a specific exercise (e.g. Bicep Curl) and i have a workout Entity that just has a name & image. The workout entity has a many to many relationship with the exercise entity. what i need to incorporate is 'session' functionality - the ability for a user to complete a workout and store the weights he/she lifted in a particular workout. E.g. i want to say that i completed my 'Leg Day' workout and lifted these weights for each exercise. So my Core Data looks like this at the moment.
schema
How would i go about storing the session data? I feel that the session must have a one to one relationship with a workout but that doesn't let me add results for each exercise in the workout... I also think i might need a dictionary to store the weights for each exercise.
Any help would be greatly appreciated as i have never really learnt about databases before.
Thanks
EDIT: Ive changed my schema to look like this
schema2
So, regarding your schema2, in database design it is typically bad practice to have relationships that form a "circle". Also, if an entity only has a single attribute, it could be reduced to an attribute of its parent.
I would probably approach your design a bit differently.
You should split your exercise entity into Exercise and Exercise_History or something similar. Then you would remove any relationship between Session and Workout and have a one to many between Session and Exercise_History.
Also, if Lift only has a single attribute, it probably shouldn't be its own entity.
If you approach it like that, you should get the desired relationships and functionality.
In Core Data I have a House Entity which has a relationship to a Room entity. The Room entity itself has a many-to-many relationship with a Door entity.
Two rooms might share the same door, so here is what I need to know:
Is it possible to have two Room entities with a relationship to the same Door entity. And when updating the properties of the Door entity, it will be the same object and gets updated in both Room entities.
Is it possible to move the Door entity from one relationship to another, without copying it?
You have a many-to-many relationship between Room and Door. This means that those relationships behave as a Set, so you can call myDoor.doors.remove(room), or .insert() to manage the entity. These are reciprocal as well, like all Core Data relationships (see here for further details). Do note your naming scheme is a bit confusing, and for example I'd recommend switching to using myDoor.rooms
in my IOS10, swift 3, xcode8 application, I have Movie in coreData.
Movie: {id:Int32, name:String, genre: [ {Genre} ] }
Genre: {id:Int32, name:String}
the way I did it, is by creating a movie entity, and a genre entity, and set up many-to-many relationship between them...
is this correct ? cause one movie can have many genres, like action, comedy
and a genre, like romantic, can be associated with many movies.
my second question is, when I am saving a new movie to CoreData, How will the Genre entity know what happened, is there like a CoreData Feature that will do that automatically? or I should add a movie to the genre Set, and add a genre set for movie ?
my end goal is to be able to search for movies by titles, or by genre.
This is fairly basic, so I would recommend researching it: CoreData Documentation
But a basic rundown is when you create a many<->many relationship CoreData creates a connections table between the two models. The way coreData works is with managed objects, meaning every time you try and access an attribute of an NSManagedObject it will be the value in the saved database.
When you add something to a many-many relationship, the connections table will create the connection, and when access it from either model, the results will be based on that connections table.
TLDR, in CoreData if you have a relationship between two models, you only need to add the connection to one of the models.
I've been studying Core Data quite a bit now, and I've now decided it's time to use it in a new project I'm doing.
Having never use it in a working project I've just come across a few issues I would like to get the communities feedback on.
I'm doing a location based application and I would like to store "outings" in my Core Data model, so for each trip I have some traditional information such as date, distance, description etc... But I also need to save location information which I'll need to plot some points on a map.
So I have a "to" and "from" object per trip, I've created a MapPoint entity with latitude, longitude and location name attributes. On my Trip entity, I've added a "to" and a "from" relationship who's destination is MapPoint.
But what do I do with the inverse property?
Because Xcode seems to give a warning it I leave it as "No inverse".
I needed to create 2 relationships on MapPoint to reference back to the Trip to the "to" and another relationship referencing the "from" relationship of Trip.
Is this correct ? I can't quite understand.
I have a similar issue with a User Entity where this is being used in several other Entities, should I be implementing an inverse relationship back to each Entity which uses User?
To keep Xcode happy it seems I need to create a relationship on User back to Trip, and back to other Entities I'm using such as an Upload, Picture entities etc... it seems to me disturbing to think a Trip has a User object, which would then have prepared to link back to an Upload/Photo... which has nothing to do with that Trip.
If you want to support inverse relationships for your to and from relationships, you can just add appropriate relationships to your MapPoint entity. Call them tripTo and tripFrom, or whatever seems appropriate to you, and set those as the inverse relationships for your to and from relationships, respectively.
As the docs explain, you're not required to model a relationship in both directions, but doing so makes life easier. What happens, for example, when a user is deleted? If you have a number of other entities related to User, then you need some way to figure out which objects were related to that user so that you can update them. If you have inverse relationships, Core Data can automatically update any related objects using the deletion rule (like nullify) that you choose. Without inverse relationships, it's up to you to fix up any related objects.
I'm not entirely familiar with Core Data, but I believe it has a form of entity inheritance.
You could make your MapPoint entity abstract and create a FromMapPoint and a ToMapPoint which inherit their attributes from the MapPoint entity.
Your Trip entity can then have two separate relationships - one to FromMapPoint and one to ToMapPoint with the appropriate inverses.
As I said - I'm no CD expert, so hopefully someone else can come along and validate/shoot-down this suggestion?
With a bit of digging I found that you can set the parent entity through the Data Model Inspector. I created this quick representation of what you've been talking about.
In my experience Core Data doesn't "require" you to have inverse relationships, but not having them leads to mysterious bugs, even if you make sure to keep your object graph consistent manually. At least I think that's what was causing the mysterious bugs.
The SQLite store uses inverse relationships to represent to-many relationships. For a to-many relationship foo from entity A to entity B, I would have thought it would create a separate table "foo" with a column A and a column B, with object ids appearing more than once in column A. Nope. It doesn't represent one-to-many relationships at all, it represents their inverses only, which are to-one relationships. It represents fooInverse as a column in entity B's table, containing object ids that correspond to A-type entities. So you must have an inverse. It seems that in simple cases Core Data can deduce what the inverse should be if you don't define it, and your to-many property works correctly. However in more complicated cases such as the one you describe, it falls over.
I am creating an app that navigates through multiple levels of one-to-many relationships. So for example, pretend that the CoreDataBooks code sample starts with a list of genres, you click on a genre and then get the list of books organized by author as seen in Apple's code sample.
Here is my problem: the Apple documentation tells me I should use a FetchedResultsController to help organize my list of books into sections (among other reasons). But when trying to figure out how to get from "one" genre to my "many" books, the Core Data FAQ tells not to use a fetch. From the FAQ:
I have a to-many relationship from Entity A to Entity B. How do I fetch the instances of Entity B related to a given instance of Entity A?
You don’t. More specifically, there is no need to explicitly fetch the destination instances, you simply invoke the appropriate key-value coding or accessor method on the instance of Entity A.
The problem, of course, is I now have my books in a set, but I want them to get them from a fetched results controller.
What is the best way to proceed here? Should I follow the FAQ, and if so, how do I manage dividing my books up into sections by author?
Or do I use a fetched results controller (which I suspect is better), in which case how do I traverse the one-to-many relationship (since Apple's oh-so-helpful answer is simply "don't")?
Many thanks for your help.
Sasha
You have a data model that looks roughly like this:
Genre{
name:
books<-->>Book.genre
}
Book{
name:
genre<<-->Genre.books
}
In your master table, you run a fetched results controller to get table of Genre objects. Then the user selects one of the row which behind the scenes selects a particular Genre object.
Since every Genre object has a books relationship that points to the related Book objects, you have automatically got a reference to all the related book objects so you don't have to fetch anything. For your book tableview you just create a sorted array of the Book objects in the selected Genre object's books relationship.
Think of a Core Data object graph as a clump of bead strings all woven together in a web or fabric. The beads are objects and the strings are relationships. A fetch plucks one of the bead/objects from the clump but once you have that bead/object in hand, then you can just pull on its string/relationship to pull out all the beads/objects related to the bead in your hand.
So, fetches are used in most cases just to find the starting objects, then you walk relationships to find most of the other objects.
That is why the Apple docs say you don't need a second fetch.