importing, saving and displaying large data sets using background thread - iphone

I have followed Cocoa is my girl friend's tutorial here, which is based on a subclass of NSOperation to fetch and load big number of records in a background thread, but in my case I have several thousands of records which take 1-2 minutes of continuous loading from a remote web service. The app have web service proxy classes generated using SudzC. There is no memory leaks detected. The problem occurs after the app finishes loading and saving this huge number of records into sqlite database (using core data), I notice that this import/save operation consumes so much memory, i.e. after this operation finishes, I use the app features for couple minutes (opening table views, writing text, etc ...), then i will see a crash that happens due to low memory, if I didn't include the import/save operation the app works fine without any low memory crash!
does anybody have a clue for this problem ?
thanks in advance.

Related

How to improve performance of application in iOS?

I have developed an application which works on iPhone-3GS, iPhone-4, iPhone-4S.
For start up process, it take 30 seconds on iPhone-4s , and take 50-55 seconds on iPhone-3gs. Tested on same network.(Its not an issue related to network or internet; In simulator it took only 5 second.)
In this start up process, App performs several actions like deletion of old data from Database, WebService calling and inserting response data into Database. Application calls almost 8 web service on main thread using performSelectorOnMainThread method(sequentially).
I am using SQLite and Compiled Query structure for insertion. I want to improve performance of application and want to reduce start up time taken by application.
Same back-end is used by Android team and they are also doing same thing. It takes 20 sec only on Galaxy note (Team android is using Object Relational Modal to communicate with Sqlite database ).
Is this the reason for faster performance ?
Is there anything that work same as ORM in Java for Objective-C to improve performance while dealing with Sqlite (processor specific , less time consuming)?
First thing is you should not be doing network operations (web service calls) on the main thread. That should be done on background threads. I don't know enough about using SQLite directly but with CoreData you can make "database" updates on background threads and just use the main thread for merging the two ManagedObjectContexts.
I imagine moving your WS calls to background threads (AFNetworking is a great framework btw), that you will see lots of improvement.
One example I have is a web-service based app that gets 7000 records from a SQL Server DB and creates an NSArray (data comes in as JSON) and that process takes 7-10 seconds. I further minimize the impact on the user by doing my auto-authentication process at the same time.
30 seconds is too long to have the user wait on something IMO.
14 best tips are available here Best Steps to increase performance of iOS App
In this tutorial, point 13 gives the info you required.

IPhone Image Caching

I want to save images fetched from a url into the NSTempDirectory(). If I store more than 100 images the application gets slow and sometimes quits. How many images can be stored in NSTempDirectory()? Would deleting the files continuously after it reaches 50 or more images be a good solution? Is there any other alternative to store images without affecting the application performance?
Clawoo is right. Check your memory management and do one more thing.
You can add your code for deleting data from temp directory inside this function: didReceiveMemoryWarning.
This function is called whenever you receive memory warning error.
If the application becomes sluggish the problem lies in your memory management implementation. Make sure you release all your objects, especially the ones that you use to download the images (NSURLConnections, NSData, UIImage, etc).
Writing all those images to disk (whether it's a temp directory or not doesn't really matter) should NOT impact your application's performance in the long term, let alone outright kill it. The application is being shut down because it most probably runs out of memory.

Data driven view iOS app

I am new to objective-c/cocoa programming. I am making an application which is to constantly sync with a server and keep its view updated.
Now in a nutshell, heres what I thought of: Initiate an NSTimer to trigger every second or two, contact the server, if there is a change, update the view. Is this a good way of doing it?
I have read elsewhere that you can have a thread running in the background which monitors the changes and updates the view. I never worked with threads before and I know they can be quite troublesome and you need a good amount of experience with memory management to get most out of them.
I have one month to get this application done. What do you guys recommend? Just use an NSTimer and do it the way I though of...or learn multithreading and get it done that way (but keep in mind my time frame).
Thanks!
I think using separate thread in this case would be too much. You need to use threads when there is some task that runs for considerable amount of time and can freeze your app for some time.
In your case do this:
Create timer and call some method (say update) every N seconds.
in update send asynchronous request to server and check for any changes.
download data using NSURLConnection delegate and parse. Note: if there is probability that you can receive a huge amount of data from server and its processing can take much time (for example parsing of 2Mb of XML data) then you do need to perform that is a separate thread.
update all listeners (appropriate view controllers for example) with processed data.
continue polling using timer.
Think about requirements. The most relevant questions, IMO, are :
does your application have to get new data while running in background?
does your application need to be responsive, that is, not sluggish when it's fetching new data?
I guess the answer to the first question is probably no. If you are updating a view depending on the data, it's only required to fetch the data when the view is visible. You cannot guarantee always fetching data in background anyway, because iOS can always just kill your application. Anyway, in your application's perspective, multithreading is not relevant to this question. Because either you are updating only in foreground or also in background, your application need no more than one thread.
Multithreading is relevant rather to the second question. If your application has to remain responsive while fetching data, then you will have to run your fetching code on a detached thread. What's more important here is, the update on the user interface (like views) must happen on the main thread again.
Learning multithreading in general is something indeed, but iOS SDK provides a lot of help. Learning how to use operation queue (I guess that's the easiest to learn, but not necessarily the easiest to use) wouldn't take many days. In a month period, you can definitely finish the job.
Again, however, think clearly why you would need multithreading.

Core Data client+server/background saving/general import question

I'm working on a Core Data-based application that has a Mac application acting as a 'server' and an iPhone as a client. Everything is going swimmingly, except I'm running into performance issues.
When the user taps an object, the server must return some objects related to that object (nothing too heavy, usually 3-4 objects) and show a UI to choose some options. This needs to be as fast as possible. The round-trip time to the server, the server pulling the data, formatting it, returning it to the client, and the client creating NSManagedObjects from the data (which cannot be optimized further) is about 200 ms. The code relating to presenting the UI (which cannot be optimized further, again) requires around 150 ms. On an iPod touch 2G running iOS 4.0, the single line of code saving the managed object context after the objects are imported is taking anywhere from 150-200 ms.
To me, this screams that I should be backgrounding the managed object context saving. However, as far as I understand it, that won't really meet my needs. If I want to save the managed object context on a background thread, then all the objects in it must have been created on a background thread in a separate managed object context, so I won't see any speed gain because it will still take 100-200 ms for the save to occur, and I'll be seeing even more overhead because I'll still need to tell my main thread to update it's managed objects from the backgrounded managed object context's save before my view controller sees that it needs to refresh itself.
Am I missing an obvious solution? Is there something about Core Data I could use in this situation that would help? I hate to throw such a general question like this out there, but I'm at a complete loss where to go from here.
Sounds like you need to move the entire server communication to a background thread. If you did that then the entire UI would be responsive no matter how long the communication with the server took.
To do this, you stand up a second NSManagedObjectContext on the background thread connected to the same NSPersistentStoreCoordinator. Then you perform your server communication on that background thread (it might even make sense to use an NSOperation) and save the changes.
Your main thread and therefore main NSManagedObjectContext listens for save notifications and when it receives one it updates the main thread and UI. This will eliminate any freezing you are seeing and the processing time becomes mostly irrelevant.

Core Data on device vs simulator

I have a simple Core Data application, with a table view and a drill down view. When I build and run in the simulator, all of the data in my database loads and the table view/drill down views function properly.
When I build and deploy to a device, my application only loads a small subset of the data (a few sections, A - C). I have no warnings nor build errors. Has anyone run into this problem? Any suggestions?
While I have not run into that issue, I would debug this using log statements. Put in logs through your loop, at the end of the NSURLConnection (assuming you are getting the data from the net) and see what is coming down, etc.
There is no reason for the default to be limiting the data and contrary to some other advice, you have at least 20mb of RAM to use even on the first device. Plenty of room to load a ton of data. Spit out the data stream to the console from the phone and see what you are getting. That is where I would look first.
I think what #theband might be talking about is the fetchLimit property of NSFetchRequest (and it's corresponding property fetchOffset). With these you can have more control over the fetching, and if you have a considerable amount of data, you will need to do that since you can't really plan on having more than about 8MB of RAM for your app on most devices.
The problem is with the device as sometimes it does not load the entire data. The solution would be checking on the limitation of data.