I have this one to many relationship entities. An NSFetchedResultsController was used for a table view to display list of teams. This part I understand and it works fine. Now in this teams table view if one selects a team, another table view will display list of members.
Currently I use an array to hold the objects from the members set, like so:
NSArray *membersList = [NSArray arrayWithArray:[aTeam.members allObjects]];
But this second stage is not clear to me. Should I need to do another NSFetchedResultsController using the selected team name as a fetch predicate for the members list table view instead of expand the fault as I did above?
If you like to track changes in those items (Members), or the data set is very large, you should use a FRC.
If your data is not updated from an external source, and is relatively "small" you could just use the relationship as your datasource.
The FRC is made for you to track changes and access your data in an efficient way (fault and un-fault objects by need, batch fetching ...).
Related
I am creating this App which can display some contents in a collection view. The data source of the collection view is stored locally by using CoreData. Each collection view cell will have a corresponding CoreData entity.
Since I am adding a "drag to reorder" feature to the collection view, I need some way to track the order of the CoreData entities. Anyone have any suggestions of how to achieve that?
Appreciate your help!
You may add an integer property to your entity type. Every time you change the order of your entities you assign the current index to this property and save the context after that. You can fetch the entities sorted by this property to restore the order.
But this solution may have two problems:
It may be not performant for large entity sets, and/or frequent updates.
The entity order may not belong to the entity content. This can be problematic, for example, if the data is to be displayed in different views in different order.
In that case you should store the order not with the entities. Instead you can store the order in a property list, e.g. in an array with the identifiers of the entities.
What I want should be simple but for some reason it's not working properly. So, when I rearrange my table view each row is saved in an array friends as a subclass of NSManagedObject in the same order as in the table view(from top to bottom). If the friends view shows two rows, friend1 and friend2, friends[0] is friend1 and friends[1] is friend2.
Whenever the table order has changed, I want the data to be stored in core data in the same order as in the friends array.
Is there any simple way to replace all core data with my friends array?
The default collection type in Core Data is NSSet which is an unordered type.
If you want a standard order like alphabetical, provide an NSSortDescriptor when fetching the data
If you want a custom order add an index field in the data model and assign indexes to the items accordingly. When changing the table view order update the indexes and later fetch the data sorted by index.
If you want to manage an order that has nothing to do with sorted attributes, you can make the relationship "ordered" which will result in the relationship being NSOrderedSet.
You can then manipulate the ordering however you desire, and when you enumerate the collection, it will be in the order you stipulate.
Note, however, that there are some restrictions on NSOrderedSet which are stipulated in the Core Data documentation.
Objects in core data has no order, just like Set.
If you have an entity with to-many relationship with friends, then you can use NSOrderedSet to keep order.
Or, you can set up a property to keep order index as a sort condition when you fetch objects from core data.
I am writing a demo messaging app to learn Core Data. In my model, an entity Conversation has a to-many relationship messages to Message. A Message has a timeStamp. I intend to display these messages in a collection view/table view with an NSFetchedResultsController. I want to know what would be the most efficient way to sort these messages. I searched around and found that I could sort the messages using:
an NSSortDescriptor on message.timeStamp
making the messages relationship ordered
adding a sequence property to message
What should be the best way to sort the messages?
The sort order should reflect your application logic:
is it logical to move messages inside a conversation? (if yes, sort by sequence number)
Do you want your data to be displayed chronologically? (if yes, sort by timeStamp)
in any case I wouldn't use the ordered relationship as a sort order as you would probably want an FRC to display your data in a table view, and he will manage memory and changes for you.
In addition to that you would want to batch fetch this relationship in any case and not simply let your table view datasource be the ordered set relationship (which will cause the items to be fetch one by one).
In an app I'm developing, I have a Core Data model which has Users and Widgets where a user can own many Widgets as their owner or watch Widgets as one of many watchers. For a screen in my app, I want to display a table view with two sections: the first lists Widgets a given User owns, while the other shows the Widgets that User is watching.
So basically what this boils down to is basing sections on whether a given Widget is related to the User by the watchers or owner relation. Is there a simple way to achieve this?
You can have two relationships between Users and Widgets. The User Entity would have ownedWidgets and watchedWidgets, whilst the Widget Entity would have owner and watchers.
User Widget
------ --------
ownedWidgets <----->> owner
watchedWidgets <<-->> watchers
Edit
Didn't notice the NSFetchedResultsController in the question title! The problem you've got is that the sectionNameKeyPath property is used by the FRC to determine sections based on one attribute. You've already done this work with the relationships, and you don't have one attribute to cover these two cases.
My suggestion would be to create two arrays from the specific User instance ownedWidgets and watchedWidgets, sorted with the same sort descriptor that you are using in your FRC, and use those for the Table View. When the FRC updates rows, you can recreate those arrays before calling [tableView endUpdates]. Saves having to alter your data model to accommodate one view controller design.
Frankly, if you already have the User object, you already have the Widgets you need via the relationships, so you don't really need to fetch anything. You might want to consider whether you really need the FRC at all.
And if you do need to use the FRC - Erik H.'s answer would be the way to go.
This depends on your data model. I think one way you could achieve this by using an intermediate object UserWidget and having an attribute (like relationshipType) for the type of relationship, owner or watcher. Then your fetch could be on UserWidgets and the sectionNameKeyPath could be relationshipType.
I've been researching this for a while and I think there are a number of solutions, but I'm not sure they are that good. It may be that I've missed something :-)
I have two tables. For each record in TableA there are multiple records in TableB. I.e. a one to many relationship. I've mapped it out in core data and generated the classes. So far so good.
My table view based UI needs to look like this:
Section 1
Cell 1: Table A: field1
Cell 2: Table A: field2
-----
Section 2
Cell 1: Table B: record 1: field1
Cell 2: Table B: record 2: field1
....
When I'm in my tableView:cellForRowAtIndexPath: it's easy to handle section 1 cells because they are different fields from the single Table A record. The section 2 cells are different. Each time tableView:cellForRowAtIndexPath: is called I need to get the correct Table B record from Table A's NSSet. And thats the problem.
NSSet doco indicates that it does not garrantee the order. Which means that if I want a specific record based on an index I have several possible techniques:
Add a sort descriptor to the core data query and use the fast enumeration to get to the record I want. I don't know if this will work because we are still working with an NSSet.
Sort the NSSet using a sort descriptor after getting the data to generate a NSArray and store that in a property before starting the table load.
I'm now thinking of a third option which is to write a decorator for an NSSet which acts like a NSArray and allows me to specify a sort field and automatically tracks changes to the NSSet. Tricky but might pay off in the long run.
neither of these answers seem that great. Is there a better way to do this?
If you just want your objects, use the NSSet accessor.
If you want the object sorted, set up an NSFetchRequest and add the appropriate NSSortDescriptors.
Then, simply perform the fetch with executeFetchRequest:error:
Even better, Since this is specifically for a tableView, use NSFetchedResultsController to populate the table view. That's what it's there for.
I've ended up with a NSArray being stored in the controller and sorting the NSSet records into it.