I have to make an iphone app for some customer.
He should be able to add some data to the app using a HTML form that update an XML file.
So I think this XML file may contain over 1000 item by the time.
Is that normal or should I work with other data storage techniques?
The XML file is used to display some information in UITableView.
1000 items doesn't seem like a lot if it's simple textual information.
I worked on an application that displayed several hundreds of complex items using UITableViews on a 1st gen iPad, the amount of data pulled from the webservice was never a problem. The problem I faced was scrolling performance and proper cell reuse.
Of course, you have to be rigorous with memory management if you expect a lot of data to be displayed in your app, else leaks will very quickly make your app crash.
Related
I'm making an app where the user can take a picture and add a title and description. But now I need to store the picture and the titles. I’ve tried making an object that contains title, description and image properties.
When it’s done I save an array of custom objects with the information on it with UserDefaults. My idea is showing in another view a table view with all the content and pictures the user has taken on the cells. I tried getting back the information with user defaults. It was working well until the user saves too many pictures. When the viewController with the tableview loads, then my app gets slower, and eventually it crashes.
I suppose the problem is when I load all the array with all custom objects, all the pictures are loaded into memory although they aren’t used and displayed for users. So I think it isn’t the best way to make what I want to make.
Is there any way better to make what I’m making or store data more efficiently and use it in tableview without using all the memory of the device?
I’m making the app from 0 again.
Can you show me how to store data and images efficiently?
There are several options for permanently storing user data on the device such that it will survive app and phone restarts. NSUserDefaults typically is for small amounts of data, such as user preferences.
When it comes time to store a lot of data, in particular big binary objects like photos, you need to decide which design you want to use. One option:
store all the photos in one directory in your apps documents and then use some simple lookup store (perhaps Core Data, or SQLite, or even a flat file) to index the photos and their metadata. Or if you don't care about indexing you can read the list of file names from the directory and sort them by time.
The other problem you are maybe having is that you are trying to load all of the photos at once for the user. As you have discovered, once you have more than a handful of photos this system falls apart. You need some mechanism to load only a few photos at a time, preferably only the ones the user needs to be displayed at that moment.
So, for example, if you are displaying the photos in a tableview, you want to only load the 10-15 photos that are visible in the table at any given time.
When storing this kind of data, you have 2 options (In fact you have more than 3 options, but saving image to the disk is IMHO complicated for this.) -
UserDefaults
Database like CoreData/Realm/FireBase...
The first one is recommended when there is not much data to save... For operating with more data, I would use database - CoreData...
For you operation you can use CoreData and NSFetchedResultsController (which is designed especially for fetching objects from the database)...
you can read the FetchedResultsController doc here... and core data basics here
Wish you best luck!
I have a tableview where i need to show around 10,000 rows (data stored locally in sqlite)
But when we jump to that view, app is getting blocked (freezed) as its loading all those rows.
Is there anyway to load data without freezing UI?
PS. Our app is rejected, is it because of this reason?
Thanks
EDIT:
They rejected and given following info
"Hello.
We noticed your app lacks native iOS functionality.
Please check out the videos for app design information,: "Getting Started
video: The Ingredients of Great iPhone Apps" and "iPhone User Interface
Design," available on the iOS Developer
Centerhttp://developer.apple.com/devcenter/ios,
and the iOS Human Interface
Guidelineshttp://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/MobileHIG.pdfin
particular, the sections, "Great
iOS Apps Embrace the Platform and HI Design
Principles"http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/MobileHIG/Introduction/Introduction.htmland
"Human
Interface Principles"http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/MobileHIG/Principles/Principles.html%23//apple_ref/doc/uid/TP40006556-CH5-SW1."
With ten thousand rows you have no choice but load your data on demand. Otherwise, your app has no chance of performing at a decent level. A freeze like you describe would definitely be enough to see your app rejected1.
This approach is rather wasteful with memory, too, because out of ten thousand rows you need at most two dozen at any given time.
A reasonably simple way to speed things up is to prepare an NSCache for your pages of data (say, ten items per page), add code that gets the total count of records, and modify the code that retrieves the data to read records from a single page (use LIMIT/OFFSET). When your table shows rows, it should try getting a page of the row from the cache. If the page is not there, it should load it from sqlite, and put in the cache. Using pages will minimize the number of roundtrips to the database; using cache will let you manage an optimal use of memory.
1 It does not look like your app has been rejected for a freeze this time around, but once you fix the "lacking native iOS functionality", the freeze will trigger another rejection.
Check this demo for lazy loading of all data along with images.
This sample demonstrates a multi-stage approach to loading and displaying a UITableView. It begins by loading the relevant text from an RSS feed so the table can load as quickly as possible, and then downloads the images for each row asynchronously so the UI is more responsive.
I'm building an app that retrieves a JSON dataset from a PHP server. The app has a view that displays a "feed" of several different newly added or updated items from the web server.
The app loads 20 of the newest items to start with, and the user can subsequently load 20 more older items, and 20 more, and so on. I want this data to persist between subsequent view changes, and quitting/launching the app.
So far I have a PHP webservice handling the JSON response by accepting a last_updated timestamp, which is sent by the iphone client with the webservice query. The server then returns any items it finds that are newer than the last_updated time.
On the iPhone side I have the connection to the webservice returning results to the iphone and displaying them in custom UITableViewCell cells. However as of right now the app will request the data from the webservice every single time.
I'm a little confused as to what's a good way to cache this data. Do I store the actual cells themselves, or create an object for each feed item type and store that? Or something else? Do I use core storage, sqlite, or some other custom method?
Thanks for any insight.
You never store data of any kind in a table view cell. Cells are intended to be reused to create the illusion of an arbitrarily long table. If you keep creating and retaining the cells as a data store you will eat all your memory very quickly.
It sounds like you do want to create a Core Data store although a plist and SQL are inferior options. The learning curve for Core Data is relatively steep but once you learn it it makes everything easier.
I have some data i want to add in to my app...about 650 categories (includes a name + id number), each with an average of 85 items (each with a name/id number).
Will the iPhone support such a large plist? I want to first display the categories in a UITableView, when a category is selected I want to display all of the associated items. Having such a large plist, im not sure if the iPhone will lag when loading the items. At over 51,000 lines it seems like...it might.
EDIT: The raw text file is 2MB
A plist can be of arbitrary length. But a plist with 2 MB of text data is a really bad idea. Even on the desktop, Apple only recommends plists with a maximum size of a couple hundred KB:
http://developer.apple.com/mac/library/documentation/cocoa/conceptual/propertylists/AboutPropertyLists/AboutPropertyLists.html#//apple_ref/doc/uid/10000048i-CH3-54402
The reason is plists must be deserialized entirely into memory before you can access a single element from the plist. This is convenient for small plists, but extraordinarily inefficient in space and time for large plists.
You should be loading your data into a database. If you do it properly, a database will only bring in the portion of the data set you need, rather than the entire data set.
I suspect it would probably take a while to load your plist, especially if you are using an XML based plist. A binary plist may be faster. You may want to consider using CoreData or a raw sqlite database to store your data instead.
The only way to be sure is to try it and see. Nothing beats actual performance timings.
That really seems better suited to pre-loading a database with. It should be somewhat smaller for one thing...
The technique is, write code to read the plist and put it in SQLlite or CoreData. Then take the database out of the simulator directory, and add it to your app - on app launch read the database from the file you have in the project.
If you need to modify the data, preload it but first copy the database into the writable directory on first launch (or basically anytime it is not there).
I have created an app which displays information in a organized manner about cultural places.
The information is subject to changes, so I want it to be downloaded from the web. But not everytime. Only once in a while, because information doesn't change often.
What I want to do is, the first time the user opens the application, it downloads all data from the web. For the moment, I parse it from an xml (which is about 100Ko), and I get a NSMutableArray of "CulturalPlace" objects. but it is very slow. And what I would like to do is, to store this data locally (in case the user has an iPod touch an is not on a wifi, or if he is on EDGE and does not want to redownload all). So the user updates data only by clicking an "update button" on the top right of the screen. Otherwise it reads it from disk.
I really don't know what could be the best solution. I thought about Core Data, but I have several Tableview imbricated (Rootviewcontroller > ListofPlacesViewController > PlaceViewController) and I really cannot find good tutorial for a simple use like mine. (the iTunes "TopSongs" sample code seems too complex).
I thought also about not parsing the xml, but instead try an NSURLConnection and get a plist file. But I never managed to read anything from the local file.
So my main question is, should I keep the xml parsing method, or should I use another format to tranfert the data from the web? And what is the best way to store and read data like an NSMutableArray of custom Objects ?
Thanks in advance for your help, sorry for my approximate english.
You could use HTML5' localStorage. It's supported by Chrome and FF on the PC and Safari on Mac OS and iPhone (to the best of my knowledge). It acts like a local database. Bear in mind that if the user selects to clear all cookies (or "private settings"), your storage goes away.
You could opt to store the XML locally, and store in NSUserDefaults the date when last updated - then on app launch you can check to see if you have a new file.
ASIHTTPRequest makes it pretty easy to say "Save the contents of this URL to a file". So you'd always save the XML to a file, and always read from that file or fetch XML if it was not yet there.
In my experience XML is indeed much slower to parse than plist, even though they're technically the same thing. Fortunately, plist's are pretty easy to deal with and the API's take care of all of the archiving and de-archiving.
Once you have your data in memory, it probably wouldn't be too hard to convert it to the much faster plist representation, check out this doc for more info: http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Archiving/Archiving.html
If your app is divided into different pages, you might also consider splitting the file into separate files, and only parsing / de-archiving the information you need when you need it (if you did this on a separate thread and displayed a UIProgressView on the main thread, the delay would probably be barely an issue to the user).