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).
Related
I'm currently looking into CoreData and need to save multiple values per key. In my case I just need to save a couple of strings, max 9, for a single Key in CoreData.
Specifically, I want to save players for a game. My game object already contains relationship objects to these players, but I also want to save the Player names as records on the game object itself, as players can be deleted by my users and I want my game objects to be immune for that.
I know in Cloudkit you can set the value of a certain key to e.g. "set of strings", and this can be done in CoreData relationships to when creating a one-to-many relationship. I was wondering if there is a by-the-book way to do this in regular CoreData key-value pairs as well.
It's easier to think about CoreData as objects rather than low-level data storage. It's not really designed as a key/value system (except in the sense that any object's properties can be thought of as a dictionary).
For the example you give, it might be more in keeping with CoreData's object persistence style to flag deleted players as unavailable rather than removing them, so that your history remains intact.
You could use an attribute of type Transformable to store your set. NSArray and NSSet conform to NSCoding so CoreData can take care of all data transforming, archiving and unarchiving for you.
I'd expect to have something like [_contact.phones objectAtIndexPath:indexPath]; available to me. Where _contact is my core data object and phones is a to many relationship from the contact. Yet this is not available to me. I'm trying to do this in my cellForRowAtIndexPath implementation (where phones would be its own section) yet I can't figure out how to do this without adding phones to an external array at the time of loading then using that instead.
Could someone give me some advice as to how to go about this?
Core data to-many relationships use NSSet. If you check "ordered" in XCode it will become an NSOrderedSet which has an objectAtIndex method.
You would not want to use the unordered set because even if you got an array of objects with NSSet's allObjects method, the ordering is not necessarily the same every time you call it.
See for instance this answer:
Ordered Sets and Core Data (NSOrderedSet)
objectAtIndexPath would make sense if the data structure were a tree and not an array.
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 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.
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.