iPhone: NSFetchedResultsController for each Entity? - iphone

I have three entities with one-to-many relationships (Book <--->> Page <--->> Text)
I want to use one table view to present Book.titles, one table view for Page.no and one view to show the Text when clicking on a Page.no.
Do I need to setup up a fetchedResultsController for each entity or can I get access to a Text object
using the Book entity - Book.pages... etc?

If I understand your question correctly, you only need one fetched results controller and CoreData will do the rest.
So, you fill an NSFetchedResultsController with all the books you want to display and present them with a UITableViewController subclass. Then when the user selects one, you pass this book on to another UITableViewController subclass which uses book.pages to get and display all the pages in that book. This idea is then repeated to show the text entities.
HTH
PS - If you aren't already, you may find it useful to use xCode's Managed Object Class generator to ensure book.pages and pages.texts are correctly set up. To use this, open your .xcdatamodel file, highlight an entity and choose File->New File and choose Managed Object Class and then follow the steps.

You can access all objects via the relationships but depending on how complex your tableviews are, it may get tricky to manage the datasource methods. It's doable though!
For instance, if you decide to fetch the books, provided you have a reference to the instance you get all pages and put them in an Array with:
Book *bookItem = [self.frc objectAtIndexPath:indexPath];
NSArray *dataSource = [[book objectForKey:#"pages"] allObjets];
Another option is to create an abstract class and make it a parent of all 3 entities, then fetch using this class which will give you an array of all books, pages and text. From there you can test for the class and populate the tables accordingly.

Related

Sample code illustrating MVC architecture in iOS

I'm trying to get the hang of MVC architecture. Say I have a plist in which there are a list of persons and each person has a few attributes like name, address and photograph. Suppose
I want to display these details in a table view. The cell title would be the name, description would be the address and the image towards the left would be the photograph of the person.
One approach I could take is to load the plist in an array-of-dictionaries in my viewDidLoad: and then display them.
However, I want to adopt an Object Oriented method by creating 'Person' class. How do I go about doing the same in this case? I believe I could start by creating a 'Person' class with three attributes:Name, Address, Photograph. What next? I would need many instances of this 'Person' class right? How would I 'load' each instance with a corresponding Person entry from the plist? Should I create another class that does this 'loading'? Do people use Singleton class to achieve his?
Could someone share some sample sample code to illustrate this? Or maybe guide me to blogs/resources that talk about this?
Hmmm, I think you are over thinking this a bit. I would just create a class that would handle my person, in this case your 'Person' class.
I would simply store each person using Core Data. Then, when it's time to display them, I would just make a fetch request and store all person managed objects into an NSMutableArray (which simply handles arrays of objects). Then you can simply use the index value to display the numerous persons in your array in a tableView.
In summary I would:
1. For every person, create instance of Person.
2. Verify if person exists in my Core Data Person Entity.
3. If not, then insert into Core Data (the object will become an
NSManagedObject).
4. For displaying, simply do a fetch request to pull all persons in your
entity. Here I prefer to store the
results into an NSMutableArray, but
that is completely up to you. Make
sure you release your fetch request
after the results are store in the
array.
5. Reference them to your table view using the index value for each
person NSManagedObject in the array.
For something that doesn't involve storing simply:
1. Create instance of Person for every entry.
2. Add Person object to array.
3. Reference each Person to table view using index value.
In the end the approach that you take will be dictated by what you want to do with the information.
As for reading the plist, I would opt for reading an XML for which all you need is an XML Parser class (there are several options for parsers). Since I don't do anything but parse the XML, I use NSXMLParser, but that choice is also up to you. Just create an NSXMLParser class (make sure that the different actions for when the parser finds a given element are in play inside that parser). So yes, you would need to make additions to the NSXMLParser for handling each element. It's really easier than it sounds.
Also, by storing in Core Data, you can always fetch the info without you using a Singleton.
I believe you are not looking for a design solution to the above mentioned question. If that is the case #A Salcedo 's version looks fine.
if you are looking for general guide lines for MVC and modeling , Martin Fowler's site offers some of the best (agile) design/modeling guidelines.
http://www.martinfowler.com/eaaDev/uiArchs.html (on MVC) and
http://martinfowler.com/design.html (many interesting design related posts).
Happy reading.

fetchedresultscontroller with two entities - predicate to target each entity?

My iPhone app has a summary page (UITableView) where I would like to show a quick overview and therefore I need to get info from several entities. It was suggested to create an abstract parent entity and have my two entities as children of this one. This do allow me to fetch the two entities using the one fetchedresultscontroller.
This works but I find that I need to filter the return a small bit. Because of the 'hack' above these entities have nothing in common so I need completely separate predicates.so from EntityA I would need "color = blue" and from EntityB "length >= 10". Because the entity I'm actually querying have none of these this doesn't work at all.
Is there a way to do this or what's the best approach here?
Niether the UITableView or the NSFetchedResultsController is designed to deal with more than one entity at a time. Moreover, it seldom makes any sense to try to do so. If you find yourself in such a situation, you probably need to rethink your data model design.
If entities are logically associated with each other then they should be linked by a relationship. If data from any two objects is to be displayed in the same tableviewCell without being gibberish then they must have some logical association and therefore should be linked by a relationship of some kind. To display in the table, you fetch one side of the relationship and then walk the relationship/s to find the other related objects.
If the logical association is strong, it should be defined as a formal relationship in the data model e.g.:
EntityA{
//... some attributes
b<-->B.a
}
EntityB{
//...some attributes
a<-->A.b
}
However, if the relationship is weak or transient, then you should use a fetched property to relate them. The fetched property dynamically searches for other entities based on a preprogrammed fetch.
EntityA{
creationDate:date
someBs--(creationDate=$FETCH_SOURCE.creationDate)-->B
}
EntityB{
creationDate:date
}
A key concept here is that Core Data is providing the entire model layer of your Model-View-Controller design. It is not just a dumb database but an active object graph that models both the data itself and its behavior. Once you have a properly designed data model, problems with the controllers and views resolve themselves automatically.
If i understand correctly, you can use notifications and send a dictionary of required information to the UITableView view controller class.

ASP.NET MVC 2: Use [Data Annotations] to reference methods that could feed DDL lists?

A generally accepted way to pass all data to a view is to have a single data model with references to both your domain model and additional data for things like drop down lists (DDL).
However, partial views (view templates too) receive only a portion of the main model, not able to access the root of the Model sent to the original view. So if your DDL lists are not static, how do the partial views get the data?
Is there a way using [Data Annotations] to reference a method which could return the possible values of a field, then use this in the partial view's DDL? Where would this method exist, in the repository?
Links or C# code examples would be very helpful.
There is no built in Data Annotations attribute that could do what you ask.
You could create your own attribute that contains a reference to a Type and the name of a static method that you can then invoke via reflection from your partial view.
Where you would place such a method depends on what you are doing, though I still think that gathering all the inputs in your controller would be better. You can always set extra items in the ViewData collection and pass those into your partial views.

Core Data - save existing managed object and show it in an another view

I'm working on an table drill-down style iPhone app that has prepopulated data. I use Core Data and NSFetchedResultsController to populate the table views. In the last level of the table view which shows an item (managed object) I want my user to be able to select that item which should eventualy be shown in another view. That other view would be a kind of a favorite list (implemented in a tab view). The user would then have a choice of deleting or adding other items to the favorite list.
My model has three entities each representing one level of table view. Higher level entity has a to-many relationship to lower level entity and inverse relationships are to-one
How do I use the existing managed object (object in the last level of table view) to save it and show it in favorite list view? Should I create new entity and establish relationship between the two?
My model has three entities each
representing one level of table view.
That is thinking backwards. What you have is three entities that exist logically in a hierarchy and the hierarchy of views reflects that logical structure. The views exist to display the data, the data does not exist to display the views. It's an important concept to grasp and if you fail to do so, your application design will always be overly complex, fragile and hard to extend and maintain. The data model always comes first and the logical relationships within the data model itself and the users interactions with that data ultimately control the UI structure of the app.
It's an easy trap to fall into because the instructional materials always start with the interface first. However, in real app design, you start with the data model first and work forward to the interface.
In this case, if you want to store favorites of some entity you have two choices. If the entity being a favorite is part of the core relationship between data and the user and you only have one set of favorites, then you could legitimately add a boolean "isFavorite" attribute to the entity and then just fetch al the entities where "isFavorite==YES"; If you have multiple list of favorites then the best method would to to create a FavoritesList entity and then relate each favorites entity to the objects it is supposed to list.
If the favorites are a minor and peripheral part of the user's interaction with the data you could store the objectIDs in the user defaults.
Yes, you could create a new entity and store the relationship. It's not necessarily the only way to do it -- you could store pointers to your NSManagedObjects in a container like an NSMutableArray -- but if you want to remember that list for later (i.e. save it between launches), it might make the most sense to also store it using Core Data.

One to Many Tableviews with Core Data

Although there is sample code in the ADC for parent/child (one to many rather than inheritance) core data, the child relationship is managed by simply loading all of the related objects into a set, and then into an array. The application I have in mind may have huge amounts of related data per parent object, therefore I would like to use NSFetchedResultsController on the child side. My attempts to do this have worked other than the controllerDidChangeContent delegate callback. With one fetched results controller on the master tableviewcontroller and another on the many side, and aFetchedResultsController.delegate = self; the delegate callbacks were fired against random objects - errors returned from invalid selector 'controllerDidChangeContent:' on things like the toolbar and sqllite whenever the underlying data was updated.
Can anyone suggest working sample code of how to use NSFetchedResultsController in both parent and child parts of a relationship.
You definitely can implement an app with several table views in which each table view has a table view controller as its datasource/delegate and each table view controller has its own fetched results controller (that may fetch objects of different entities and/or with different filter predicates and/or with different sort descriptor(s)).
It would be hard to give you specific recommendations without knowing more about what your are doing (with code examples) and the specific issue(s) that you are having.