I want create attribute of "event" entity that will have a short list of events what the correct way to make it?
I think the right way is just use array but how can I do it? if someone can give me code example it will be nice.
Don't listen to any advice regarding foreign keys - they do not exist in Core Data. What you have to do is link your Event entity to another (or itself) with a relationship.
It is not clear why an event would have a short list of events. Maybe you want to distinguish event types or something similar. You could then create a new entity EventType and establish a to-many relationship in the Core Data Model Editor:
Event <<----->> EventType
Now an event could be linked an arbitrary number of EventType objects. You could use a relationship name like allowedEventTypes for each event and access this set (not an array, mind you, but an NSSet with unordered unique objects):
NSSet *types = event.allowedEventTypes;
Once you master the core data modeling technique, the coding becomes exceedingly simple.
Related
I'm trying to figure out what's the recommended way to implement enum with associated values in Core Data data model. Let's say I have a book entity and I want to save in database how I got the book, like:
it's bought by me (or other family members)
it's borrowed from someone (e.g., a colleague)
it's given as a gift by someone (e.g., a friend)
This would be an enum in swift:
enum WhereItCameFrom {
case Bought(who: String, date: Date, where: String)
case Borrorwed(who: String, date: Date, dueDate: Date)
case GivenAsGift(who: String, date: Date, forWhat: String)
}
I'm thinking to implement it in data model using inheritance , as below:
Introduce a parent entity WhereItCameFrom and define the above cases as its children entities.
Define a to-one relationship from Book to WhereItCameFrom. Its deletion rule is Cascade.
Define a to-one relationship from WhereItCameFrom to Book. Its deletion rule is Deny.
See the diagram:
I'm wondering if this this the right way to do it and I have a few specific questions.
1) What's the typical way to implement enum with associated values?
I think my above modal is good. But just in case, are there other better ways to do it?
2) Is entity with no attributes normal?
In above diagram, WhereItCameFrom doesn't have any attributes. At first I added a type attribute to it to indicate if it's a Bought, Borrowed, or GivenAsGift entity. But then I realized this information is implicit in its child entity class type, so I removed it. So the only purpose of the parent entity is to hold the relationship. Is this use typical in Core Data?
3) Will the old object be removed automatically when modifying relationship at run time?
Suppose I modify book.whereItCameFrom relationship value at run time. Its previous value is a Borrowed object. Its new value is a GivenAsGift object. Do I need to delete the Borrowed object manually (I mean, doing that explicitly in application code)?
I guess I should do it. But given Core Data is a framework helping to maintain data consistency in object graph, that seems awkward to me. I wonder if Core Data has some feature that can figure out the Borrowed object is not needed and delete it automatically?
Thanks for any help.
UPDATE:
In the third question, after the old Borrowed object is disconnected with Book object, is my understanding correct that, from the Borrowed object perspective, the peer object has been delete and hence the peer object's Cascade deletion rule is applied to the Borrowed object? If so, then it will be deleted automatically. I think the real question here is if deletion rule applies to relationship update or not. I'll do some experiments on this later today.
A few thoughts...
1) What's the typical way to implement enum with associated values?
I think my above modal is good. But just in case, are there other better ways to do it?
I can't comment on typical ways of implementing enums with associated values, but your model seems to make sense. One word of caution: if you search StackOverflow for questions regarding entity inheritance, you will find several answers advising against using it. The way CD implements subentities (at least for SQLite stores) is to add all the attributes of all the subentities to the parent entity SQLite table. That's handled for you "under the hood" by CoreData, but the SQLite table can potentially end up being very "wide", which can affect performance. I've never found it an issue, but you might want to have that in mind if you have lots of data and/or the entities are more complex than you indicate in the question. Subentities can also cause issues in some rare situations - for example, I've seen questions indicating problems with uniqueness constraints.
2) Is entity with no attributes normal?
It's unusual, but not a problem. However, as all three subentities have date and who attributes, it would be wise to move these from the subentities to the parent WhereItComeFrom entity. (Otherwise, as noted above, your parent entity table will have three columns for date (one for each subentity) and three for who).
3) Will the old object be removed automatically when modifying relationship at run time?
No. If you modify the book.whereItCameFrom relationship value at run time, with a GivenAsGift object replacing a Borrowed object, CD's graph management will ensure that the Borrowed object's book property is set to nil. The cascade rule does not prevent objects being "orphaned" in this way and you must manually delete the Borrowed object.
I'm struggling with creating a suitable Core Data model for my app. I'm hoping someone here can provide some guidance.
I have two entities -- "Goals" and "Items". The Goals entity contains only a goal description, but any goal may have any number of subgoals, and these may extend multiple levels in a tree structure. Subgoals are to be contained within the same entity, so presumably the Goal entity will contain a pointer to "parent" which will be the parent goal of any subgoal.
There will also be an "Items" entity that contains a couple of text fields and a couple of binary items, and must be linked (ideally, by a unique identifier, perhaps objectID) to the particular goal or subgoal the item(s) are related to.
I am totally fumbling with how to set this model up. I know what attributes need to be in each entity, but the relationships, particularly between goals and "subgoals", has me stumped. I don't seem to be able to turn up any good examples of tree structures in Core Data on the Internet, and even the couple of books I have on Core Data don't seem to address it.
Can anyone here help an old SQL programmer get headed the right direction with these relationships in Core Data? Thanks.
Have you tried creating a one-to-many from Goal to itself, and a one-to-one from Goal to Item? The only thing I would worry about here is circular references.
Also, read Relationships and Fetched Properties in the CoreData Programming Guide.
Here is how it is done:
You set up a to-many relationship from Goal to Item in the model editor. Don't use any ids, foreign keys etc. This is old-fashioned database thinking - you can forget about it. Here we are only dealing with an object graph. The database layer is just an implementation detail for persisting the data.
Make two more relationships in entity Goal to itself: a to-one called parent, a to-many called subGoals. Make them the inverse of each other. Simple!
QED is correct, you can create a to many relationship on goal (call it subgoals) as well as a to-one relationship on goal (call it parentGoal) and set them as inverses to each other.
Then create another to many relationship (call it items) on the goal entity, with the inverse being a to one relationship on the item entity (call it goal). Then you're all set. You don't need to link items with a unique id, just add them to the items relationship.
Also note that if you did want to give items a unique id, do not use the objectID. The objectID should only be used as a temporary id as they are not guaranteed to remain the same. In fact they will change if you ever do a Core Data migration.
One way, though not really great, is to create a another entity, say subGoal, and each goal has one subGoal and each object of subGoal has many goal.
I am new to iOS programming and I'm doing up a simple function of an iOS application. Currently, I've created an entity called Players, and I'd like the entity to have a property, in which it stores other NSManagedObject like an array.
This is because I want a player to be able to have friends in the game and this is the way I've thought of; I could just access a player's friend's list via
[playername friendList]
May I know if this is the way to do so? Because for an entity's attribute type, I couldn't use NSMutableArray or NSArray as its type. If it is, may I know how I can store it? If not, is there a better way to achieve that?
This is the purpose of relationships in the Core Data model. Add a relationship between the two entities (and an inverse) and add the managed objects to that relationship.
See this section of the Core Data guide.
You need to create a relationship between the models, which are represented with NSSet (or NSOrderedSet, by checking "ordered", if the order is important.)
Ordered Sets are similar to arrays, except all the objects are distinct (no duplicates).
I have 3 tables in my core data tables.
Item table: items, which has an ID column and a connection to a properties table.
Properties table: it has a propertyValue column and a connection to item table and a connection to property table.
Property table: it has a propertyName column and a connection to properties table.
The property table contains a propertyName called "price".
The properties table contains a propertyValue "20" for the property "price".
Do you think I can sort the Items table by price?
I am using a NSFetchedResultsController and I am creating a NSFetchRequest for it.
I have tried to write a NSSortDescriptor with a comparator block object for the NSFetchRequest. It isn't working. After this I tried to write a NSSortDescriptor without any selector or block object, I just setup a key called "dealPrice" and created a category on the Item managed object with a method called - (NSString *)dealPrice. It wasn't working neither.
Do you know any other method? Or do you know the solution?
You've obviously got a bad case of SQL fever. Your trying to treat Core Data like an SQL wrapper and that is messing everything up.
Core Data is not SQL. Entities are not tables. Objects are not rows. Attributes are not columns. Relationships are not joins. Core Data is an object graph management system that may or may not persist the object graph and may or may not use SQL far behind the scenes to do so. Trying to think of Core Data in SQL terms will cause you to completely misunderstand Core Data and result in much grief and wasted time.
A Core Data datamodel should not be configured depending on the needs of the UI or any other non-data requirement. Instead, it should accurately model/simulate the real world objects, events or conditions that the app deals with.
In this case, you are modeling:
A type of property that has a name and a price.
An item denoted by an id of some kind
A relationship between one or more particular property instances and one or more instances of item.
Therefore, your data model only needs two entities connected by a relationship. You don't need a "join" because the relationship handles the connection between the two entities automatically.
The simplest model has just a one-to-one relationship:
Item{
id:string
property<-->Property.item
}
Property{
name:string
price:number
item<-->Item.property
}
If each Item object can have several associated Property objects then you would have:
Item{
id:string
properties<-->>Property.item
}
Property{
name:string
price:number
item<<-->Item.properties
}
If each Property object can have several associated Item objects:
Item{
id:string
property<<-->Property.items
}
Property{
name:string
price:number
items<-->>Item.properties
}
How you configure your sort descriptors depends on the details of the relationships and which entity's objects your tableview will display.
What I would first recommend is to stop thinking about CoreData like a database. It is NOT a database. The things you call "tables" are actually Entities. Think of them as objects, that have properties and relationships to other objects. Think about making your data model as simple as possible. Do not try to optimize your structure for database performance etc. The actual backing schema is not under your control.
With that in mind, from what you've posted about your data model, it seems like you should be able to collapse into at least 2 entities instead of 3 (perhaps 1 but not sure without seeing your entire data model). Then, you should be able to do a simple fetch on the Items entity with a predicate that sorts on a property of it's related object.
It sounds like your real object model is and entity named Deal with an attribute named "price".
I have an entity called Project and another entity called Employee. Employees work on multiple projects.
Project entity has project name.
Employee entity has First name, last name, departmentid number.
I want the data to show up in section header table like this
Project 1
Dept1
-firstname1, lastname1
-firstname2,lastname2
dept 2
firstname3, lastname3
firstname4,lastname4
Project 2
Dept1
-firstname1,lastname1
How can I do this? I don't have to display department names, but it has to be sorted that way.
I am using Core Data & UITableView. I need to construct NSFetchResultsController for this.
I think the root of your question comes from the fact that a to-many relationship results in an NSSet when you access it from the from object of the relationship (ie: Project->Employees - results in an NSSet of employees). NSSets are, of course, unordered.
And the answer is this:
You'll need to sort your employee NSSets by hand. I suggest you convert the NSSet to an NSMutableArray, and then use -sortUsingBlock: or something along those lines to do it. To keep yourself from having to re-sort it every time you need it, store it as a member variable of your Project class. In doing so, it should be pretty easy to create it lazily, and only re-sort it when the dataset changes, which will be better for performance.
You MIGHT be able to do something with a subquery in Core Data... but I think you might find that'll hit the disk more often than you might like. (Just a guess there) The technique I've suggested above is a bit less magical, a bit more brute force, but it'll work, and you'll know exactly how it behaves forever.
Use fetchedResultsController to get your 'Project' entities and you will be able to access and display the Employee NSSet in your tableview datasource methods via their relationships.