Best Way to save data locally on the device in iOS app - ios

I am working on my first iOS app which will be deployed for both iPhones and iPads. The app contains data that needs to be bundled with the app, which will be used when the device will be offline.
The offline version has atleast 35-40 records with each record containing images(which would be bundled in the app, only names will be saved), and a varchar field which would be atleast 1000 words and a boolean field.
I have found three possible solution for the same
Save all the fields using database (SQlite or Coredata), however
I am concerned about the table which will have 1000 words. But since
the varchar field might vary, I need to allocate max 2000 (or more,depending on the actual length of keywords)
limit (which will lead unnecessary allocation of memory resources)
Another Approach I would like to have is save the information in form of json locally and use it as and when required and save the boolean fields(only true locally in NSUserDefaults)
Use the JSON Approach as discussed above and create a database for managing the boolean fields.
I would like to seek the opinion of StackOverflow community on what would be ideal/optimized approach for this scenario. Also, I am open for any other approach as well.
Edit 1
Proposed provisional databased structure
Listing Table
id -> int (autoincrement)
name -> varchar(25)
imagename -> varchar(10)
desription -> varchar(2000)
favorite -> boolean

It sounds as though the text field (with the 1000-2000 words) is static text that is bundled with the app and can not be changed by the user of the app. If that's the case, then you can store that data in the app bundle with plist files, or JSON files and load it on demand (assuming you don't need to search though it).
Then, if each of those records has only a single boolean value that is changeable by the user, those could be stored in NSUserDefaults very easily (since you've stated you're only dealing with 35-40 records). You'd use the id to link the boolean to the data file.
You could use Core Data or Realm to store the data, but it may be overkill if you don't need a search feature and the user can't change the text. But if you do go with a database option, be aware that you can not store static data (the text), in a location that is backed up by iCloud, or Apple will reject your app. Regardless of whether you use iCloud in the app or not. So if you were to create a Core Data persistent store and save it to the users Documents folder, then load in all the static data, you will be rejected. You would want to save that data store in the users Cache folder so that iCloud doesn't back it up. The issue you'll hit after that though is that you want the user's choices that are your boolean values backed up. This means they need to be stored in a different place. Core Data does have a feature that lets you create Configurations where it will separate the user changeable data from the non-changeable data, but again, that's overkill for your case.
I'd recommend starting with Realm over 'Core Data` for such a small dataset. It's much easier to get up and running.

If you need to look into the fields, CoreData is th best approach, because you can easily access your data using NSPredicates, ( Like an SQL where statement` ).
But if you need to load everything at each launch, you can just store everything to a file ( plist, son ... ), because it is really more easy to managed, and to update ( If you update CoreData Model, the change may be complicated on the App update ).
So my short answer is :
If you need to teach into your data => Core Data
Else => File on local Storage
Do not use UserDefault to achieve that, this is not designed for it.

It is depends on you data base's complexity and operation.
See, first thing is whatever data base system you used, there is no performance difference.
Every database system has different complexity and operation limitations.
For example, It is very simpler to use NSUserDefaults to store and retrieve data.
But if you required to do relational operation between bulk data then it is better to use sqlite or core data. Relational database operations are easily performed by sqlite or coredata compare to others.
There is another option is property - list also available if you data is only type of key value pair.
Core data is totally based on sqlite. In root core data itself using sqlite.
Difference between core data and sqlite is : core data provides more flexibility to use it but it is comparatively hard or complex to learn. Where sqlite not provide flexibility compare to core data but it is less complex to learn and use. Flexibility means for example : you can see visual representation of core data. Can visually add entity or attributes etc.
So, select data base as your need and complexity of use or base on operations that you will required to perform. Your database is not much big and not complex and not required any relational operations or multiple tables then you can use user defaults or property list also.
Hope this will help :)

Pitching in with an option.
To make it easy for yourself later on, I would suggest using CoreData. This lets you easily manage the products for reading and writing. This also gives you a good persistent storage.
To the description issue; you could store the description for each product in its own file with a unique name that references the product you store in CoreData. In your CoreData entity you define a descriptionFile, which will hold the file path.
This approach makes it easier for CoreData when you fetch the objects, maybe you want a browse view where you don't need to display the description, therefore you don't need to load the description text into memory. When a product is selected, load the description file for that product and display the text within.
Happy Coding :)

Related

iOS: Should I use Core Data or NSUserDefaults?

Background:
I have an app that retrieves a list of restaurants from a database, each have an individual array of basic information about them (hours, name, address, etc). I would like to retrieve that information from the server on the apps first load, but then have it stored within the app itself, with either NSUserDefaults or Core Data, since the information is unlikely to change. The max number of restaurants I would be storing is about 25, is that a small enough data collection to use NSUserDefaults?
I have looked at similar questions with storing data with over 1,000 records, but I am only storing a small array.
Question:
NSUserDefaults is much easier to use than Core Data, so if possible I would like to avoid using Core Data. In my case, will there be a performance problem if I am storing my list of restaurants in NSUserDefaults instead of Core Data?
Depends on the
size
structure of data
requirements re integrity of the data
Just an Array of 10 or 20 "restaruants" I would certainly store in NSUserDefaults. But only when I am sure that this will never become more complex. Because when you later extend your model but started off with NSUserData then you may remain with NSUserDefaults just because you avoid migrating it to Core Data during the upgrade of an installed app.
So for more complex structures including references and when you have further plans with your app towards more functionality that may require more entities, then you should go for Core Data from start.
BTW, it is not that complicated as you may think.
However, instead of abusing NSUserDefaults, you could simply write an NSArray to file using -writeToFile:atomically: and -initWithContentsOfFile: to read them in.
NSUserDefaults is not intended for data, it's for storing simple key-value pairs like user settings and flags. Core Data is a bit hard to learn at first, but definitely worth it, even for simple applications.
If it really is a small, simple data set that won't change very often, you can also store some data in a local plist (i.e. save NSArray or NSDictionary to plist using writeToFile method). This isn't very different from using NSUserDefaults in terms of performance, although I think it's cleaner and easier to manage. If it never changes you can also include the plist with your app resources in XCode by creating a plist file and filling it in with your data.
Considering the amount of the data, user default or a specific plist/json file are all good. CoreData is definitely overkilling.

Advise where to store data for iOS app

I have created an app using ionic and cordova and now I want to remake it on iOS. I am working with iOS for the first time, and I cannot figure out how to store data.
For example: I have a form where user has to input some data, but the inputs are not in one view, there must be several views. I used to create empty array and just put everything step by step, but now i can't use same view controller on multiple views. Tried to do it with core data, but core data cannot store arrays. My object would look something like this:
var sampleArray = (
duration: 13,
dayOfTheWeek: Thursday,
personList: [
(name: Rocky,
age: 26),
(name: Ralph,
age:23)
]
)
The question would be: How could I make an input form which would be on several views and where should I store the data, and later I would be able to store all the data into core data?
You can work with persistent data in several ways on iOS.
User Default
This is a tool that is used to store small amounts of information like user settings, preferences etc. Don't use it for data that will scale with application usage (e.g. like notes in notepad app). Documentation will answer all your questions about User Defaults.
Database
You have Core Data as an out of the box solution which is build on top of the SQLite and takes some time to learn, but from my experience it's worth the effort. You are free to use pure SQLite or other database type, but it requires more code and probably custom frameworks.
Text files
You can use arbitrary XML, JSON or CSV files to store your data. Tooling is rich (e.g. NSXMLParser or SwifyJSON just to name two) and if you look on Github, you will find what you need. You can also use build in combination of NSCoder and NSKeyArchiver / NSKeyUnarchiver which are easy to grasp.
Binary files
Finally, for a local storage you can use binary files i.e. images. This is too advanced topic to cover here, but I want to share an example of Open Raster file format. It is used to save informations for drawing apps (eq. GIMP) and inside, it is basically an XML file and a bunch of images compressed to zip and named as .ora file. Creating your own specification for a hybrid format is not that hard.
Network repository
Just to not overlook other methods, you can use remote database API to store data outside of the device, but of course you need your own host and some backend skills.
I hope I didn't miss something important. I just wanted to sum up this knowledge in one place for future reference.
As the first comment says, your question is quite large.
When you say 'one form on several view', I consider it as 'one form per view'.
Keep It Simple S... ;)
(Except if you use page control for your form.)
Basically, you have three ways to store data :
NSUserDefaults :
Store data in Dictionary for later use
File :
Save data to a File (why not .csv like ?)
CoreData :
You can persist arrays as binary data in Core Data
There are numerous tutorials on these topics.
www.raywenderlich.com site is a good one to begin...

Simple read-only data storage in iOS (with easy editing and visualization)

I've used archiving, user defaults, and some Core Data in my apps before, but I'm running into a wall re: the best method for my current scenario. I have an app that needs to instantiate some objects from a resource file each time before it's used. An example of one of the objects could be a "MathQuestion" object that has the properties:
questionID (Int) - 2341
questionText (String) — "What is the square root of _?"
questionVariable (Float) – "4"
correctAnswer (a block/closure that returns a Float) – "{return sqrt(value)}".
Ideally, I'd just have something like a spreadsheet with columns for each of these properties and rows for each of the different questions. That way, I would really be able to visualize all the data and make quick changes during development.
My app uses Parse, which is great for visualization and easy editing of values, but for this case, I'd rather the resources remained on the device and not the Parse server. I've been considering Core Data up till this point, but (this could be my inexperience with C.D.), I'm unaware of any way to manually edit the data—and it seems like it may be overkill for what I'm looking for anyways. (I basically just need a way to upload and parse a CSV!) Any advice would be welcome!
I would still recommend Core Data. It is simply the most efficient and scalable mechanism to store and retrieve data.
When I work in your kind of scenario, what I often do is work with a spreadsheet where I can conveniently edit the data. You could edit a CSV version of it that you have included in your target. (If this does not work for you, you could also copy paste into a separate CSV file right into Xcode.)
On every start, you just trash the data store (using NSFileManager when creating the NSPersistentStoreCoordinator). Then you call a method that reads in the CSV and stores it in Core Data.
Once you are done with development, you simply keep the sqlite file (you can include it in the bundle and copy it over, or re-generate it from your CSV the first time the app runs).

Fastest and light way(Sqlite or core data or plist or csv or flat file)

I have a simple problem to solve but want to know which is better pattern to use and understand the reason for the choice.
Problem :
I want to create a utility which developers can use to check whether the feature should be enabled/disabled depending on the server package version.
eg : server package versions like 10.234, 11.1 etc and client versions 9.3,10.2 etc
Validation on client to see min version on server package for feature to be enabled/disabled.
example data would be like "search lookup feature >= 10.234". And sometimes complex situation need to even check client version whether the feature should be supported.
edit:
Note: Application is very huge and memory is full for most of the time. (thousands of records of organisation data.) So memory is bottle neck.
Just it even flashed to mind to used macro as to do all comparisons and returning value.
I think Plist would be heavy as all the objects would be in NSDictionary and even to access one object, I'll be holding all data.
I want to reduce memory overhead and comparisons too.
For Light data, Use NSUserDefaults or PList. SQLite and Core Data is overkilled.
Updated Answer for Updated Question:-
For server package versions/your app version or other light weight data, you can always use NSUserDefaults or PList.
For records of organisation data, you might want to consider Core Data.
Yes, you can use 2 different types of persistent storage inside your app.
If your data is never going to change, or grow you better use NSUserDefaults, plist or csv file. If you think that user should have the ability to change or add new entries to this data file you better go ahead with CoreData
Plists, csv, and flat files have low overhead for small to medimum amounts of data (and for data where you use all or nearly all) of it.
Systems that only use some of the data on any given run AND have large amounts of data AND have the data structured so SELECT can use an index can be faster (lots and lots faster) with a database (SQLite, or CoreData with the SQL Persistant store).
As a gut feel I expect your problem could be handled well by SQL, but only if you are talking about 1000s of configurations not 10s or even 100s...but you would be better served by benchmarks then my guesses. Go code :-)

Initialize Core Data With Default Data

I have a basic question regarding populating Core Data with data. I am building an application, which will show ATMs on a map. I would like to ship the application with a preloaded database, but to give users the option to receive updates when they launch the app. I am thinking about using a property list for the update. Basically send a plist of all the ATMs, parse that plist and populate the sqlite. I will have around 7000 entries in the property list file, each entry containing 5-6 keys with short string values. But according to the Apple iOS Developer Library:
You can create a property list—or some other file-based
representation—of the data, and store it as an application resource.
When you want to use it, you must open the file and parse the
representation to create managed objects. You should not use this
technique on iOS, and only if absolutely necessary on Mac OS X.
Parsing a file to create a store incurs unnecessary overhead. It is
much better to create a Core Data store yourself offline and use it
directly in your application.
Should I still be sending a property list or rather think for an alternative solution to update the application's database?
P.S. I am thinking about using a Rails app for providing updates - basically sending a plist file.
I had nearly the same question a few months back, did quite a bit of searching to find a nice easy answer, failed to find it and eventually settled on a roll-your-own solution that took a bit more time than I would have hoped, but was at least very helpful in learning to understand Core Data.
Basically the solution was to write a little utility that parsed my source data (which for me is a comma-separated text file, parsed using the quite handy 'cCSVParse' library - http://michael.stapelberg.de/cCSVParse ) and inserted it into Core Data Managed Objects and then saved that off as a sqlite persistent store. Then the sqlite store(s) can be shipped with the app, and uploaded by the user when they buy more data.
You could write a conversion from plist (or whatever) into the core data representation within the app itself, but if the data is just going live out the rest of its days in some core data form, why not let your beefy dev box do the heavy lifting before you send the data to the user, instead of shipping the data to the phone and making it do the work?

Resources