What is the best practice to reference model objects in views with Core Data? - iphone

I have an NSManagedObject that described an animal, it has the attributes "name", "species", "scientificName" etc. I display all animals in a UITableView and managed the NSManagedObjects with an NSFetchedResultsController.
To provide my table view cells with the information necessary to render the content so far I just weakly referenced them to my NSManagedObject describing the animal. However, sometimes the NSManagedObject should get faulted and when the table view cells are redrawn, they re access the properties of the object and thus prevent the fault.
What are the best practices to provide view objects with information when using core data as data source? If possible I would like to avoid copying all attributes of the NSManagedObject over to the table view cell.

I believe it is a good practice to clearly separate the Model, View and Controller layers. Especially making sure the Views are not holding Model state. Holding on to a NSManagedObject holding on to a Model object. Copying some data is unavoidable.
I usually implement a method for "painting" the View with the Model data. Something like this in the UITableViewCell subclass:
-(void)configureWithAnimal:(NSManagedObject*)animal {
self.nameLabel.text = [animal valueForKey:#"name"];
self.speciesLabel.text = [animal valueForKey:#"species"];
// Etc.
}
This way it is a single line of code in the UITableViewController subclass to setup the cell, independently of newly created or reused cells. And if many tables wants to reuse the custom cell then not all f them need to reimplement the code to seeing up the cell.

Related

NSOutlineView and Core Data 1 → Many Relationships

I have a Core Data model that supports a 1 → Many relationship (1 Folder to many Phrases). At the moment I'm just displaying the Phrases on a flat NSTableView using Core Data Bindings to a NSArrayController to glue everything together - this is working happily.
I'm trying to experiment with an NSOutlineView to achieve the same result but showing the folders as well. I've tried a similar binding structure that I'm already using with the NSTableView but I'm not making any headway. What steps should I take to move from a flat NSTableView to a NSOutlineView with 'depth'?
Here's my MOM:
Top level folders, bottom level phrases. No nesting. I'm not an animal.
NSTreeController
I have a NSTreeController bound to the array controller for arrangedObjects on Controller Content
It is set to 'Entity Name' mode with an entity name of Folder (this feels wrong)
phrases is set to the children key path
Prepares Content is true
It's mOC is set to a valid mOC
NSOutlineView
Outline View Content is bound to the Tree Controller using arrangedObjects as the Key and string as the Key Path
The Phrase NSManagedObject
has an extension called 'phrases' which returns an empty set, since it'll never have children.
When I do this, I get this as a result:
[APPNAME.Folder copyWithZone:]:
The tutorial that got me this far had nested objects and only one type of entity, where as I have two. What do I need to have an accurate representation of my core data objects in a NSOutlineView?
NSTreeController and NSOutlineView work in the same way as NSTableView and NSArrayController. To use NSTreeController you don't need a NSArrayController, you can put the treecontroller in entity mode.
my entities are not called Table View Cell
Remove the column binding, it is for cell based ouline views. Bind the content of the outline view to the tree controller and bind the text fields in the Table View Cells to the Table Cell View.
The tutorial that got me this far had nested objects and only one type of entity, where as I have two.
This is a problem because NSTreeController has only one childrenKeyPath and the textfield in the outline view can only bind with one key. As far as I know there are two workarounds.
Solution 1: Create a subclass of NSTreeController and override
- (NSString *)childrenKeyPathForNode:(NSTreeNode *)node
the managed object is node.representedObject.
Implement the delegate method outlineView:viewForTableColumn:item: and use a different view for each entity.
Solution 2: Create NSManagedObject subclasses and implement calculated properties for children and display so all entities answer to the same keys.
I think this solution feels wrong, managed objects shouldn't contain code for views, but it is very easy to implement if you already have NSManagedObject subclasses.

Referencing nsmutablearray to Data Model

I have a design issue which I am trying to analyze in my current project and thought maybe someone could help me figure this out. I have an nsarray object which I filter through predicate, and I want to set that object as my data model through view controller. First, is this a good practice of doing so? Since, I want to have an access of that object through out my transaction. I am not dealing with any database, plist, or core data model at current, these are just custom data model class I have created.
Thanks.
It's very common for a view of some sort to be backed by an NSArray, or an NSMutableArray. (Particularly, a UITableView, which can provide a single cell for each object in your array.)
Depending on the scope of your project, you can either investigate using Core Data for binding your model to your data:
CocoaDevCentral Core Data Overview
Or, for something a bit easier but less robust, you can look into implementing the methods defined in the UITableViewDelegate and UITableViewDataSource protocols, if you want to populate the cells of your table on a per-request basis.

How do I manage models & views in an iPhone app?

I have a bunch of model objects that inherit from NSObject (Result). And I have a bunch of view objects that inherit from UIView (ResultView). They exist in a 1:1 relationship (one model for one view). In my controller I have an two arrays: one for Result objects and one for ResultView objects. The controller displays many of these result views and they can be added/deleted/reordered. Trying to keep 2 arrays in sync (results & resultViews) isn't working out. How should I approach this problem?
I'm considering initializing a view object with a model object (eg: an initWithResult: in my ResultView class and then retain a pointer to the Result object in the ResultView). Then I could do something like ResultView.result to access model data. Is there a better solution? This would break MVC, wouldn't it?
Unless you're trying to persist these model objects in a DB or something similar, I would put a view property on the model objects. If you don't have to create the view for any reason, then just nil it out to save on memory.
Does it break MVC? I guess. But if your model objects will always have a view associated with them, it starts to go into the blurry line area. No programming god will send you to hell for breaking the standard a little bit.
Do what's clean, optimal, and easiest for another programmer to understand when looking at your code.
Ok, if I understand your question correctly, the model objects are persistent while the views are dynamically created/deleted. You are relying implicitly on the index of the two arrays to achieve the mapping of two parts. One simple way is to add a "model object id" in your view class. Then you can easily reference to the correct model object in the view.

Maintaining data sync between UITableView cells and array of model objects

I have a UITableView where each cell corresponds to a model object.The list of these model objects are kept in an array inside a singleton object that manages the model objects. The UITableViewController subclass holds a instance variable that references this singleton object. The model objects update their internal data asynchronously from the web. What's the best method for updating the table cells when the corresponding model object finishes reloading its data? Should the model objects send out a notification? Can the table cells use KVO to receive changes from the model objects? Is there another option? What is the best practice here?
I found a solution by subclassing UITableViewCell. Each cell maintains a reference to the model object that it corresponds to and observes a boolean isLoading property of this object. When the loading state changes, the cell updates it's data. In other words, the cell (view) object observes the model object, then requests data to present upon the model object state changing.
I'm not sure that is the best solution but in a previous project I was calling the message reloadRowsAtIndexPaths:
NSArray* paths = [[NSArray alloc] initWithObjects:indexPath, nil];
[tableView reloadRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationMiddle];

One UITableView - Multiple DataSource, best design pattern?

This seems like a typical problem, but I have a UITableView that has identical behavior for two separate data sources. What is the best way of going about designing the class hierarchy to have as little duplication and if/else conditions? The view controller is going to do the same exact thing to both data sources, they're just unique in their data set. Should I have the parent controller just set its data source/respective title?
The same issue is relevant as well when using a UISegmentControl for displaying two views with the same interfaces, but different data sources.
Be careful with your terminology here. A UITableView has something called a dataSource but you seem to be referring, essentially, to two different sets of data.
In the case you're suggesting, in the table's dataSource (the object that adheres to the UITableViewDataSource protocol), I'd have three arrays.
currentlyViewedArray
datasetOneArray
datasetTwoArray
In the dataSource methods, use the currentlyViewedArray as the source of the table's data.
Then, set the currentlyViewedArray to whichever array you want to view:
self.currentlyViewedArray = self.datasetOneArray;
[theTableView reloadData];
You can use the UISegmentedControl to switch between the two arrays.