Swift - Save huge array of strings with UserDefaults - swift

I have a social app, where the user can like photos... So, in order not to wait for fetching the data from the server, I want to store to the device, an array of strings, containing the photos' objectIds.. The question is, considering the user can like thousands of photos, is it good practise to use UserDefaults to achieve that?

EDIT
As pointed out by Eric Aya in the comments, NSUserDefaults aren't loaded automatically into memory when the app launches.
NSUserDefaults are loaded into memory when your application launches If you have a particularly large amount of data stored in NSUserDefaults then the time it takes your app to launch to load NSUserDefaults will be impacted by the amount of IO required to retrieve your data. The intended use case for NSUserDefaults is to store small sets of data such as default user settings.
A Plist may be a better solution (NSUserDefaults is just a Plist, the difference being is it's loaded automatically for you when the app launches). You will still have the same issues with load times when you decide to grab the Plist as you will be loading a file (the Plist) into memory. You will be able to handle this with something like a progress bar or an activity indicator which gives the user a nicer experience. than having to wait longer than usual for an app to open. CoreData is another option (usually intended for more complex data structures than strings, on the flip side it gives you the capability to scale your storage needs very easily if the complexity of your data increases), there's a fairly steep learning curve involved but it's a wonderful feature and is well documented by Apple: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/
I would also recommend storing the data on a server where you could expose it via an API and cache the response using a Plist/CoreData/Whatever you like. This way if your users change devices they will still have access to the same data as it's stored remotely.
Good luck!

Related

How can I store images and strings locally on Swift

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!

Persistent storage of object data

i am developing an sample app where i have N number of custom button with images present in the screen.I can able to perform following operation(drag drop,rotate,change color etc.)upon these buttons.
I can also able to draw line on the screen.
So now i want to persist these data so that on restart of application i can able to see my previous objects.What is the best solution to do this?
You've got three options, all pretty simple:
store the data in user defaults
store the data in a plist in the documents directory
use core data
In all cases you'll need to transform your data into property list type format (strings, numbers, data, dictionaries, arrays). User defaults would be frowned on if you had a large amount of data. Core data could be overkill. A plist is probably your best bet on the information you have given.
You'll need to store your data either each time it changes or when the application goes into the background, and restore it if needed on launch. I say if needed, because if you are just resuming from background, everything may still be present if iOS hasn't sent you any memory warnings or closed you down.
Core Data. Use a managed object to represent each button with attributes like "color","position_x", "position_y", etc.. use sqlite as the persistent store.

Any concept of iPhone Memory Store? memcache or redis for iPhone?

I'm looking for some concept of a memory store for my iPhone App. There are some complex NSDictionaries I want to store in memory and read from, rather than parse the JSON stored in a database over and over.
If there is no such thing as a memory store, what options do I have? I tried putting inside user defaults, and reading it back again, but it seems to take just as long as the JSON parsing...
I decided to create a singleton class that contains the data I needed and it's being used by the entire app. Easy, simple and gets the job done
Storing in a binary plist in persistent memory is faster than an xml plist.
Use the NSPropertyListBinaryFormat_v1_0 option with NSPropertyListSerialization.

for the given configuration should I attempt to use NSUserDefaults or go to CoreData?

For the given configuration I need to be able to store should I consider using NSUserDefaults, or go to CoreData?
The configuration for the iPhone would be roughly like this, note the 3 levels so to speak:
Items (NSMutableArray)
aString: NSString
aString2: NSString
aDate: NSDate
aDate2: NSDate
aBool: BOOL
aTI1: NSTimeInterval
aTI2: NSTimeInterval
Keywords (NSMutableArray)
keyword: NSString
keyword: NSString
PS New to iPhone so haven't got any invested time into any particular persistance approach yet.
Looking at the structure, i would recommend you to use NSDictionary to save the data at specific keys.
whether to useCore Data or NSUserDefault depends whether you want the data to be saved on a plist and be available every time you start your application or to share the data among the classes without saving it in a file, respectively.
NSUserDefaults and Core Data perform two different task and you should pick the one appropriate to the data you wish to persist.
Despite the historical name, the NSUserDefaults are intended as the application preferences. (In the old Next days, there was complicated set of network based preference domains of which the NSUserDefaults was merely the bottom/local most set of preference. In iOS, they have become just the preferences and the enclosing domains have been removed or hidden.) If the data you wish to persist regards the application state e.g. users choice of UI layout (such as fonts or startup mode), last open view, last viewed web page, then that information should go into the defaults.
Core Data by contrast is designed to implement the entire data model layer of a Model-View-Controller design app (which all iOS apps are.) It's primary task is not persistence/saving but modeling/simulating the logic and relationships connected to the app's data. Really, the model layer is the guts of the apps logic and the controllers and views just interface.
As such, Core Data is overkill for saving little pieces of data like you have. You can certainly do it but it's like driving a semi-truck down to the QuickyMart to haul back a quart of milk.
Perhaps more importantly, if the data is application state data then it needs to be in the user defaults so that (1) the data is available when the app starts and (2) it is available anywhere in the app.

best way to store data locally and update from web from time to time?

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).