Sharing a core data database between two instances of a table view controller - iphone

I'm making a shopping cart. In one tab, I have a table view controller with all the items. I have another tab, I have a shopping cart that has an 'add item to cart' button which segues to another table view controller whose class I set the same as the table view controller of the items in the other tab.
But the problem is, the one from the segue does not load the rows anymore, so I get a blank cells. How do I fix this?
Does my question have anything to do with passing NSManagedObjects among objects?

You have to be very careful passing ManagedObjects between threads. dispatch call is likely to do so. Instead, contain the processing to one thread per ManagedObjectContext. I prefer using a specific worker thread that main calls which then dispatches the messages asynchronously to private methods.
This may or may not be the cause of your particular problem, but I've had significant issues with Core Data working across threads that are likely to at the very least pop up later for you.

Related

Kendo UI Mobile MVVM - How to handle two list views that navigate to a single detail view?

I have two ListViews (in separate views). These views are bound to separate view-models but the ListViews contain the same entity type. Both views allow the user to select an item and navigate to it's detail/edit view.
What do I need to do to share this detail view between the two list views?
Here is what I have tried:
Assign the selected item to a property in the detail view's view-model
This initially appeared to work but actually breaks Kendo MVVM. Since the item is in the list view's view-model, assigning it to a property in another view-model causes problems.
Refresh data in each view's show event
While this almost works, it has a couple problems. 1) Getting fresh data all the time can be slow. 2) When saving changes in the detail view and navigating back to the list view, the save is async, so there is no guarantee that those changes will have been persisted before the call for ListView data. This also negates one of the benefits of MVVM and observables.
Share the view-model across views
The examples I have seen that have a list and detail view, have both views sharing a view-model with a selectedItem property. This is not possible in my particular case because I have two list views that navigate to the same detail view - not to mention that I prefer to have a separate view-model for each view so that the view-models don't become a huge mess. Am I supposed to have all views share a single view-model?
What am I missing?
Maybe you could extract the observable model to a plain object model with the toJSON() method, and then create a new observable model from it by wrapping it again. This should clear the existing bindings and avoids the conflicts you've found in your first approach.
var model = kendo.observable( otherModel.toJSON() );

Cancelling edits: NSUndoManager or separate NSManagedObjectContext for editing?

I have a View Controller that manages a view which is always shown in editing mode. The view is essentially a table view similar to that of a contact's details in Apple's Contacts app. The model underneath my view is represented by a 2-level object graph comprised of a root entity - call it R - having a to-many relationship to a child entity C. Now, R is a large object (it has 20+ attributes, all editable but non-mandatory). By default, R has n children (n being a configurable value), but child objects can be added and removed to/from R's collection via my editing view and C's attributes can be edited as well. Note that C entities include attributes for image meta-data, so there may be images picked and associated with the model while editing.
Edits on R and its children are performed via the main table view form, as well as from "secondary" views to which I navigate (back and forth) in order to collect the required information, depending on the case.
My question is, how would you implement a "Cancel all edits" in this situation, i.e. how should I isolate all my edits to easily revert to the state prior to editing? Using a NSUndoManager with my main NSManagedObjectContext? Having a separate NSManagedObjectContext for editing? What would be the trade-offs for each?
I don't care for redo. I am looking for an idea/solution that would strike a balance between the amount of memory used while editing vs. the ability to save the user's data if the app is interrupted while editing.
Thank you for all your ideas.
I would advise against a design that has the same edit function in two different views. Each view should represent objects of an different entity/class of the data model and should therefore have different editors and undo management.
The contact app shows how this is done. You can delete an entire contact in the master tableview and individual contact attributes in detail view. The changes in each view are committed when the view disappears. Such a setup not only makes undo management much easier but makes it much easier for the user to understand exactly what changes they are making.
If you want to stick to your original design, I would suggest keeping the undo stack of the master tableview until the master unloads completely i.e. not when the detail view loads.
I concluded here that for NSUndoManager to work properly with Core Data, it must be done in a child context. Since a child context gives you "Cancel all edits" capability, you don't also need NSUndoManager. Therefore, every cancel-able View Controller should do its work in a child context This means, for example, controller A would use a child of the document's context, and if it segues to controller B, that would use a child of A's context (child of child of document context). If the users presses Save, the context is saved which automatically propagates the changes up to the parent. If the users presses Cancel, the context is discarded thereby ignoring the changes. The only complication is with an iPad app where A and B might both be visible and the user presses Save on A (but this is probably just bad design).

iPhone programming guideline : List / detail / modify

I have a program that displays a list (a TableView).
When the user clicks an item, it's detail is shown.
On the detail view, the user can ask to modify it so a modify window is shown.
Here, the user can ask to delete the item.
I would like at this time return to the list with the item deleted from the list and from the data source.
There may be thousands of methods to do this, but I wonder which is the best / good one.
Could you help me, and/or give me a good reference to read about this ?
I think he ask how to get from view number 3 back to first view.
Then you can put your three views inside a UINavigationController and call on the last view popToRootViewControllerAnimated:
at least Two options:
Delegation - Create a protocol called something like: TableDetailModifierDelegat
and add methods like modifierDidChangedItem:(id)item
or modifierDidDeleteItem:(id)item
and to the modifying view controller add instance variable id so when you done editing or deleting you will call the appropriate methods.
of course you will need to make your table view controller implement the protocol you created. if you modified or deleted an item you should update your data source and reload the data to the table.
also pass the Table View Controller as the delegate when creating the Modifying View Controller.
Passing The Data Model.
This is much more simple to implement.
you can simply pass your data model to the modifying view controller, and make the changes directly to the data model.
You should keep the data model as Instance Variable in the modifying view controller.
when you done, dont forget to reload the data to your table.
In this instance, you could simply remove the data from the data source the UITableView is using and then call the reloadData method on the table. (As you're editing the data in question, you'll presumably have a suitable method/reference by which to delete it.)
As a bit of reading, I'd recommend Apple's Table View Programming Guide for iOS - this provides a lot of useful background information.

How to Handle an Indefinite Amount of TableViews in an iPhone drill-down app

I've Created a UITableViewController subclass. Do I only need one controller? Do I just instantiate multiple instances of that one subclass?
The iPhone App I'm building will start with a Table of a list of people. If the user taps a person, a new table will be pushed in with a list of Companies they've worked for. If the user then taps a company, they'll see a list of Job Positions. And if they tap a position they'll see a list of people holding those positions.
This could go on forever, and the user could always back up the list.
The App Delegate instantiates the Navigation Controller and the Table View Controller and then pushes it onto the Navigation Controller. But when a user taps a row, now the TVC is creating another TVC.
Is that right or should the
AppDelegate be instantiating all
TVC's? Or does it work out since
they all get pushed onto the Nav
Controller anyway?
Does each Table View instance
need to have a different name or can
they all be called 'mainTVC' or
something like that?
tableViewController *mainTVC = [[tableViewController alloc] init];
Won't I run out of memory? Do i
need to start dropping Table Views
when they're 2 or 3 levels away from
current, and then re-create it if
the user backs up to it?
No need to create multiple TableView's, what I've done in the past is simply re-bind to a different datasource. So keep one TableView and have a datasource for people, then companies, etc...
I'd create a view controller for each type. Presumably you'll want to have special display characteristics like a custom tableview cell to display job positions slightly differently then you would people names.
Other then that, #Ben Gottlieb's answer should work quite well. Use lots of view controllers and handle the didReceiveMemoryWarning: method.
One more thing, if the user drills down so far that you want to say they'll never go all the way back (sort of like having an undo stack) you can use the setViewControllers:animated: UINavigationController method to reset the stack to a certain size (say 15 to implement an 'undo buffer' of 15). With this method you can make sure that the first view controller is always your root view controller and the rest are all drilldown instances.
Option number (2) looks good. You can push quite a lot of view controllers onto the stack before memory becomes an issue. The system will clean up most of the heavyweight memory hogs (ie, the views) in the didReceiveMemoryWarning: method. If you're creating a lot of in-memory structures, you may want to clean them up in that method (be sure to call the inherited method).
To answer your third question, as long as you don't have huge data stores in memory, memory shouldn't be an issue. You SHOULD NOT under any circumstances "drop" tableviews - this would lead to crashes(and there's no way to do non-FILO additions/removals to the navigation stack anyway). Under memory pressure, you should only free "nonessential" items like caches. However, this shouldn't be an issue.
Also, if you have more than 3 or so levels, chances are you need to rethink your UI. If users are drilling down 10 levels, it will be tedious to navigate the stack back.

How can I get a method to call in a class while the user is in a view of another class?

I have an iPhone app based on a tabBar and tableViews. I want the user to be able to click on one tab and access options for filtering the data in the initial tableView.
The problem I'm having is that while the user is selecting filter criteria, I want the main table (not visible) to update. The reason this is important is that I want to show how many cells are still in the table as it is being filtered in the navigation bar.
Currently, the method for filtering the main table (-handleFilter) is called in the viewWillAppear method of my rootViewController class. How can I call this method from my "searchOptions" class?
Thanks for the help!
It sounds like you're conflating too much between your model and your controllers (assuming you're following the MVC design pattern). The other controllers besides the main table should be able to query the model themselves to display the count information without asking the main table controller.
I could be misunderstanding something though, a little more information on what data you're using and how it's being filtered in the controllers attached to the other tab bar items would help.
The most straightforward way would be to give the options controller a pointer to the list controller. Then you can call the method directly.
Other options include defining a method/property on some global object (like your app delegate) to access the list controller from elsewhere in the app, and using a more decentralized mechanism like NSNotificationCenter to pass that information around (rather an a method call), or relying on the model itself to notify all of the controllers accessing it when it changes (possibly using Key-Value Observing, or an explicit delegate protocol).