Open UIManagedDocument take too much time - iphone

Recently, I'm working with a timetable app in iOS, and i get trouble with Core Data.
My app has a main user interface kind of like the original calendar app created by Apple, and i save all my events data in the Core Data database.
I create a UIManagedDocument in order to fetch data from database by using its NSManagedObjectContext, and everything works just fine.
However, i need to use the NSManagedObjectContext to fetch data several times in several different view controllers during the runtime. And every time i do this, i need to reopen the UIManagedDocument, but open the document take too much time(it may take 2 seconds or even more, i have to display a spinner in view).
So here are my questions:
What's the right way to open a managedDocument?(I mean like open it during the lunch image time?)
Is there a way to only open the managedDocument once and keep it open during runtime?(So i can use its context all the time)
Does data store in the managedDocument i create?(I found that if i delete the document, data was gone)
Thanks.

You will get lots of different opinions on how to do this but basically you should only have to open the document once. This is done by some object that does the work and stores it so it can return it again when asked by a different view controller.
Many people create singleton's for this or put it in the App Delegate. I have implemented a protocol that lets me put it where ever it is convenient for a particular application without my other code having to know anything about the object that returns the information. As long as it responds to the protocol it can be the App Delegate, a singleton class, or any other object type.
See importing AppDelegate
The protocol that I put in the above example just returns information about where the database is. In my actual implementation I have an openDatabase method with a call back to let me know when it is done plus automatic initialization and updating methods.
You can also improve your performance by having the open operation happen off the main thread. This keeps your UI responsive but does not show the data any faster and you have to be carefull about managed object contexts and the threads they are in.
Good luck...

Related

mvvmcross editting a complex object over multiple pages and saving data

I'm fairly new to mvvmcross and the mvvm model in general. I have been trying to create my own cross platform app for several weeks now and I'm stuck at what would be good practice. I have two main problems, I hope somebody can help me with
Question 1:
I have a complex model with many properties, sub items, and sub items in those sub items. Also, many values are automatically calculated based on other values.
I implemented the MvxNavigatingObject everywhere, and all values are correctly notified when changes occured. So far so good.
Now I want to let people use the app to change the values in my model. But because there are so many input fields, I want to divide the data over several pages. But each page has it's own view model of course. That means reloading my large object every time the page changes.
To solve this, I created a DataHolderService, which is loaded as a singleton on all the view models. Then I let my viewmodels change the data in the DataHolderService and I never have to reload the data.
But I wonder, is this good practice? It feels a bit strange to be doing this. Are there other possibilities? Like using the same viewmodel on multiple pages?
Question 2
I would like to save my data to the database so it persists between sessions. I have a SQLite database and am able to save the data using a button. But if the user forgets to use the save button and the app is put in the background until the system eventually kills it, the data would be lost.
I therefore added a timer, which periodically saves the data to the database. But I can understand that this isn't very good practice. What would be a good way to save the data back into the database without having the user needing to press a save button? Is there an event/function that will fire before the view model is disposed?
Its a bit hard to understand exactly what you are trying to achieve, however.
Is it not better to use a list of questions rather than spreading it over multiple pages?
We have created a similar page recently. If your data is shown as a checkbox/radio buttons/spinner etc, we save them immediately when the value has changed.
For saving text, we use a 1 second timer that starts when the user starts typing, is reset if the user changes the text within that time and is saved otherwise.

iOS Asynchronous NSURLConnection triggering behaviors on different views than the one that call it

Me and my team are currently rookie developers in Objective-C (less than 3 months in) working on the development of a simple tab based app with network capabilities that contains a navigator controller with a table view and a corresponding detailed view in each tab. The target is iOS 4 sdk.
On the networking side, we have a single class that functions as a Singleton that processes the NSURLConnection for each one of the views in order to retrieve the data we need for each of the table views.
The functionality works fine and we can retrieve the data correctly but only if the user doesn't change views until the petition is over or the button of the same petition (example: Login button) is pressed on again. Otherwise, different mistakes can happen. For example, an error message that should only be displayed on the root view of one of the navigation controllers appears on the detailed view and vice versa.
We suspect that the issue is that we are currently handling only a single delegate on the Singleton for the "active view" and that we should change it to support a behavior based on the native Mail app in which you can change views while the data that was asked for in each one of the views keeps loading and updating correctly separately.
We have looked over stackoverflow and other websites and we haven't found a proper methodology to follow. We were considering using an NSOperationQueue and wrapping the NSURLConnections on an NSOperation, but we are not sure if that's the proper approach.
Does anyone have any suggestions on the proper way to handle multiple asynchronous NSURLConnections to update multiple views, both parent and child, almost simultaneously at the whim of the user's interaction? Ideally, we don't want to block the UI or disable the buttons as we have been recommended.
Thank you for your time!
Edit - forgot to add, one of the project restrictions set by our client is that we can only use the native iOS sdk network framework and not the ASIHTTPRequest framework or similar. At the same time, we also forgot to add that we are not uploading any information, we are only retrieving it from the WS.
One suggestion is to use NSOperations and a NSOperationsQueue. The nice thing about this arrangement is you can quickly cancel any in-process or queued work (if say the user hits the back button.
There is a project on github, NSOperation-WebFetches-MadeEasy that makes this about as painless as it can be. You incorporate one class in your classes - OperationsRunner - which comes with a "how-to-use-me" in OperationsRunner.h, and two skeleton NSOperations classes, one the subclass of another, with the subclass showing how to fetch an image.
I'm sure others will post of other solutions - its almost a problem getting started as there are a huge number of libraries and projects doing this. That said, OperationsRunner is a bit over 100 lines of code, and the operations about the same, so this is really easy to read, understand, use, and modify.
You say that your singleton has a delegate. Delegation is inappropriate when multiple objects are interested in the result. If you wish to continue using a singleton for fetching data, you must switch your pattern to be based on notifications. Your singleton will have responsibility for determining which connection corresponds to which task, and choosing an appropriate notification to be posted.
If you still need help with this, let me know, I'll try to post some sample code.

Delegates and Notifications in Objective-C

In my AppDelegate, I download some data from a JSON feed. I am downloading a now/next/later schedule for a few channels. I have three different view controllers for each now, next and later. In each view controller, a user can add/remove the channels so when that happens, the newly added channel data has to be downloaded again.
Since the data is downloaded in the AppDelegate and stored there, how would I pass it to the three view controllers? Should I implement three separate delegates? Keep in mind that when adding a new channel, its data has to be downloaded again (which I am doing outside the AppDelegate now).
Any help please?
Thanks
This is basically a matter of style and your approach isn't invalid as such.
I'd do it another way, though - the AppDelegate is not meant to be used as a workhorse and having several AppDelegates at the same time is simply impossible.
Here are some thoughts about how this could be done (though it's of course not the only proper way):
First, I'd employ Core Data or some other sort of storage which is available from anywhere within your app.
Then maybe I'd introduce some sort of "data controller" class (maybe a singleton). This class should handle both download of data and the distribution of that data to your viewcontrollers as requested.
By having one central controller for that purpose, you'd ensure that data gets downloaded only once because the controller knows exactly which data is already in stock.
Your viewcontrollers would neither be responsible for managing downloads anymore nor would they access the data on disk by themselves. They'd just make a request to your data controller and get a callback when the requested data is available - no matter if it was on disk already or has been downloaded for the occasion.
This keeps your VCs slim and focused and reduces the pain of making changes to your interface.
Toastor's answer is correct and as he says, there are several ways to do this. One is to call a data access class and change the values OR listen for changes on the values. For the later, the Key-Value Observing Programming Guide says the following:
KVO is particularly useful for communication between model and
controller layers in an application.
A controller object typically observes properties of model
objects, and a view object observes properties of model objects
through a controller.
In addition, however, a model object may observe other model
objects (usually to determine when a dependent value changes) or even
itself (again to determine when a dependent value changes).
Another is to make the dependency explicit, maybe passing a data access class saved in your app delegate. See Object-oriented design question, iPhone.

Approaches to save some NSManagedObjects but not others?

I'm working on a Core Data iPhone app that pulls remote resources from the web into NSManagedObjects and saves them locally.
I want the user to be able to designate which of these objects should be saved. This means that some will be saved, but many should be deleted. However, I might want to save and delete at different times - I'd prefer to save designated objects immediately (in case the app crashes), but still keep around the other objects because they're hanging out in table views and such.
One approach I can think of is to have a different persistent store - one for stuff that will be saved, one for stuff that won't; this way I can save the "should be saved" store at any time. However, I would much prefer to keep objects of the same type in the same domain.
Another approach would be to just save at the very end - negating any ability to recover from a crash. But saving at the end would allow me to parse out any objects that weren't designated "should save".
And that's really what I want - a "shouldSave" method in the NSManagedObject class, or at least a save method that I could fire at select objects. But as far as I can tell, neither of those exist.
So, if anyone has any other suggestions, please let me know! It would be greatly appreciated.
CoreData is not for object serialization, it is an object graph serialization. That is an important distinction. Once you have an NSManagedObject it is associated with a context, and CoreData handles saves at context level since that is the only way it guarantee any sort of object graph consistency. In other words, you can't save individual objects because if they have relationships with other objects you would need to also save those objects and it quickly cascades out to the whole graph.
You seem to be worried about crash recovery. If the app crashed and the user relaunched it would they expect to see just the items they saved, or everything that was on the screen before they crashed? If it is the former you should just delete them at save time and remove them from the users view (with some animation), if it is the later you should commit out everything, and potentially delete the objects you are not interested in at another time.

Good strategies for REST -> XML -> Core Data -> UITableView?

What are good practices for asynchronously pulling large amounts of XML from a RESTful service into a Core Data store, and from this store, populating a UITableView on the fly?
I'm thinking of using libxml2's xmlParseChunk() function to parse chunks of incoming XML and translate a node and its children into the relevant managed objects, as nodes come in.
At the same time that these XML nodes are turned into managed objects, I want to generate UITableView rows, in turn. Say, 50 rows at a time. Is this realistic?
In your experience, what do you do to accomplish this task, to maintain performance and handle, potentially, thousands of rows? Are there different, simpler approaches that work as well or better?
Sure, this is a pretty standard thing. The easiest solution is to do the loading in a background thread on one MOC, and have the UI running on the main thread with its own MOC. Whenever you get a chunk of data you want to have appear (say 50 entries), you have the background MOCsave:.
Assuming you have the foreground MOC rigged to merge changes (via mergeChangesFromContextDidSaveNotification:) then whenever you save the background MOC the foreground MOC will get all of those changes. Assuming you are using NSFetchedResultsController it has delegate methods to cope with changes in its MOC, and if you are using Apple's sample code then you probably already have everything setup correctly.
In general CoreData is going to be faster than anything you roll yourself unless you really know what you are doing and are willing to spend a ton of time tuning for your specific case. The biggest thing you can do is make sure that slow things (like XML processing and synchronous flash I/O caused by save:) are not on the main thread blocking user interaction.
Joe Hewitt (Facebook app developer) has release much of his code as open-source. It is called Three20. There is a class there that is great for fetching internet data and populating it into a table, without the need for the data beforehand. The classes used for this are called TTTableViewController and TTTableViewDataSource.
From here, it would not be much of a stretch to store as CoreData, just subclass the classes as you see fit with the supplied hooks.
If you are worried about too much data, 50 at a time does sound reasonable. These classes have a built in "More" button to help you out.
From the Three20 readme:
Internet-aware table view controllers
TTTableViewController and
TTTableViewDataSource help you to
build tables which load their content
from the Internet. Rather than just
assuming you have all the data ready
to go, like UITableView does by
default, TTTableViewController lets
you communicate when your data is
loading, and when there is an error or
nothing to display. It also helps you
to add a "More" button to load the
next page of data, and optionally
supports reloading the data by shaking
the device.
No one has mentioned RestKit yet? My friends ... seriously, you have to check this out. If you are doing anything with REST on iOS (and now on OS X) and particularly if you're wanting to work with Core Data ... PLEASE have a look at RestKit. I've saved countless hours implementing some pretty complex data synchronization between a server and my Core Data models on iOS. RestKit made it so damned easy, it almost makes you sick.