Where to store Dictionary data in iOS - ios

I am developing iPhone app,i have one doubt
I have an NSMutableDictionary which contains data in this format
dict at 0th index:
"ProductId":"77386",
"ProductImage":"http://static.abcd.com/images/product/large/design_gallery_slide_green - Copy (2).jpg",
"Productshortname":"Apple iPhone 5c 16GB",
"categorycode":null,
"categoryid":8,
"categoryimage":"",
"categoryshortname":"",
"favorite":"0",
"price":"31500",
"productnameinUrl":"apple-iphone-5c-16gb",
"storecount":"10"
dict at 1st index:
"ProductId":"11386",
"ProductImage":"http://static.abcd.com/images/product/large/design_gallery_slide_green - Copy (2).jpg",
"Productshortname":"Apple iPhone 5s 16GB",
"categorycode":null,
"categoryid":8,
"categoryimage":"",
"categoryshortname":"",
"favorite":"1",
"price":"31500",
"productnameinUrl":"apple-iphone-5s-16gb",
"storecount":"18"
dict at 2nd index:
"ProductId":"31386",
"ProductImage":"http://static.abcd.com/images/product/large/design_gallery_slide_green - Copy (2).jpg",
"Productshortname":"Apple iPhone 4s 16GB",
"categorycode":null,
"categoryid":8,
"categoryimage":"",
"categoryshortname":"",
"favorite":"1",
"price":"31500",
"productnameinUrl":"apple-iphone-4s-16gb",
"storecount":"38"
and so on...
What i want to do is, i want to store this dictionary indexes some where in my directory and i want to fetch it after some time or even after closing and opening the app after few times.
where should i store this kind of data ? is there any storage for strong this kind of data?
Please help and thanks in advance !!

You can store the data in NSUserdefaults and can access any time and anywhere as you want
yourdict;//Your NSDictionary Object That contains the data to store
[[NSUserDefaults standardUserDefaults] setObject:yourdict forKey:#"dict"];
[[NSUserDefaults standardUserDefaults] synchronize];
At the time of retrieval of data,
dict = [[NSUserDefaults standardUserDefaults] objectForKey:#"dict"];

You've already chosen an approved answer but I'll throw my thoughts in anyway.
This information looks like it could get large.
The user defaults isn't designed for large chunks of data. It's really meant for small bits of information, such as boolean preferences etc etc, not to be treated as an easy-to-use database.
Some problems with the user defaults:
The defaults file is read and parsed when you launch your app, regardless of whether you need your information from it at that time or not. This is because other parts of your app also use it for storing their bits of info too.
The entire defaults file needs to be parsed in order for you to retrieve anything, even if you just want a single entry.
You don't choose when the defaults file is parsed. You can't do any smart threading if it becomes huge (say you put 1000 products in there)
I'd recommend either writing the dictionary to it's own plist using NSDictionary's writeToFile: and reading using initWithContentsOfFile: (this still suffers from point #2 above)
OR
Using CoreData/sqlite to write the information to a real database.
NSDictionary methods: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/Reference/Reference.html#//apple_ref/occ/instm/NSDictionary/writeToFile:atomically:

An other option (And better in my experience) is to use - NSCoder, this option is great as you can use an Object with normal properties to access your data, which make your code more readable.
You can read about it here - NSCoding / NSKeyed​Archiver by NSHipster
An here is the reference - NSCoder docs

NSDictionary has a writeToFile: method which will do it for you.
NSDicationary writeToFile:Atomically:

use NSUserDefault and save your data like this in array
Here you can use this in anyway in your application for store value of NSUserDefaults.
// --- Saving
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// saving an NSString
[prefs setObject:#"TextToSave" forKey:#"keyToLookupString"];
// saving an NSInteger
[prefs setInteger:42 forKey:#"integerKey"];
// saving a Double
[prefs setDouble:3.1415 forKey:#"doubleKey"];
// saving a Float
[prefs setFloat:1.2345678 forKey:#"floatKey"];
// This is suggested to synch prefs, but is not needed (I didn't put it in my tut)
[prefs synchronize];
Here you can use this in anyway in your application for get value of NSUserDefaults.
// --- Retrieving
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// getting an NSString
NSString *myString = [prefs stringForKey:#"keyToLookupString"];
// getting an NSInteger
NSInteger myInt = [prefs integerForKey:#"integerKey"];
// getting an Float
float myFloat = [prefs floatForKey:#"floatKey"];
Thanks & Cheers ..

Looks like there can be more amount of data, so the best approach is to use core data to handle this scenario.
You can check few tutorials on how to use core data - Link1 , Link2
There are advantage of using core data over NSUserDefault and file system, as those load all the data at once and you might face some issue in performance.
You can also check following links which will illustrate you performance of different mechanism used to store data - PerformanceLinks1 PerformanceLinks2

try this
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"audio.caf",#"pictureAudioKey",
#"audio.m4a",#"englishAudioKey",
#"audio2.m4a",#"spanishAudioKey",
#"audio3.m4a",#"frenchAudioKey",
#"audio4.m4a",#"germanAudioKey",
#"audio5.m4a",#"italianAudioKey",
#"audio6.m4a",#"chineseAudioKey",
#"image.jpg",#"photoimagekey",
#"name.txt", #"identity",
#"imagename.txt",#"numberkey",nil];
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *dictionaryPath = [documentsDirectory stringByAppendingPathComponent:[[self imageNameTextField]text]];
dictionaryPath =[dictionaryPath stringByAppendingFormat:#"dicitonary" ] ;
NSDictionary *savedDictionary = dictionary;
NSLog(#"The Save file is:%#", savedDictionary);
[savedDictionary writeToFile:dictionaryPath atomically:YES];

Related

NSUserdefault and core data

what is NsUserdefault ? and how it can be used to store peristent data of app .
Please clear my doubt on when to use them and how they can be useful performance wise ?
With the NSUserDefaults class, you can save settings and properties related to application or user data.
For example, you could save a profile image set by the user or a default color scheme for the application. The objects will be saved in what is known as the iOS “defaults system”. The iOS defaults system is available throughout all of the code in your app, and any data saved to the defaults system will persist through application sessions. This means that even if the user closes your application or reboots their phone, the saved data will still be available the next time they open the app.
Performance
The NSUserDefaults class caches the values internally so the lookup is extremely fast. The overhead of [NSUserDefaults standardUserDefaults] vs an instance variable is so small that you wouldn't even notice it if you did it 5 million times in your code.
The NSUserDefaults class acts very much like something called a Property List (aka plist). Plists are limited in what kind of objects they can store. The six types plists can store are:
NSData
NSString
NSNumber
NSDate
NSArray
NSDictionary
Usage:
NSUserDefaults is used to store values that belongs to users settings and needs to be remembered even when app is killed and re-launched. Having said that, as posted in another answer, we should put only light weighted objects in NSUserDefaults.
For other heavy wight save and reload user file system. For things that involve search on saved data use Core Data.
Writing To NSUserDefaults:
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("Your Object", forKey: "yourKey")
Reading from NSUserDefaults:
let defaults = NSUserDefaults.standardUserDefaults()
if let value = defaults.stringForKey("yourKey")
{
print(value)
}
Other Useful Convenience Methods:
func setBool(value: Bool, forKey defaultName: String)
func setInteger(value: Int, forKey defaultName: String)
func setFloat(value: Float, forKey defaultName: String)
func setDouble(value: Double, forKey defaultName: String)
func setObject(value: AnyObject?, forKey defaultName: String)
func setURL(url: NSURL, forKey defaultName: String)
Storage Size:
As long as there's enough space on the iPhone/iPad, you can store NSUserDefault values. All those values is stored into a .plist file, and this file is very small, most of the time under 1 kb. But keep this as light as possible.
This is the piece of code i made as a demo use of NSDefaultUser .
to save data
NSString *name = _tf_name.text;
NSString *email = _tf_email.text;
int age = [[_tf_age text] integerValue];
// Create Instance of NSUserDefaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// Set the object and YOU name the key, we are defining the key here
[defaults setObject:name forKey:#"firstName"];
[defaults setObject:email forKey:#"email"];
[defaults setInteger:age forKey:#"age"];
// Call Sync to Save Objects
[defaults synchronize];
// Load Data
// Get Saved Objects
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *name = [defaults objectForKey:#"firstName"];
NSString *email = [defaults objectForKey:#"email"];
int age = [defaults integerForKey:#"age"];
NSString *ageString = [NSString stringWithFormat:#"%i", age];
// Load UI
_tf_name.text = name;
_tf_email.text = email;
_tf_age.text = ageString;
NSUserDefaults are used to save very light data, where as other approaches are good to store bigger amounts of data, that the app work with.
NSUserDefaults makes is incredible easy, as you don't have to worry about files, entities, fetches,…. It is all done in one line.

Saving Successfully, but not Visibly Editing plist

So this is my first time trying to save data in an iOS app. I've pieced together this code from various answers on this site in order to save a high score for a game I'm making. I created a plist named saves.plist (in my Supporting Files folder) and added a row of key #"bestScore" and type Number. The test log returns that the save is successful, and everything works; however, when I go to look at the plist after, nothing seems to have changed (the value of bestScore is 0). Am I saving to a different plist that is automatically created in my code? If this is the case, what is the point of being able to create plists in Xcode, and what is the best practice to use here as far as where/how to create/store/access plists?
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.fm = [NSFileManager defaultManager];
self.destPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];//Documents directory
self.destPath = [self.destPath stringByAppendingPathComponent:#"saves.plist"];
// If the file doesn't exist in the Documents Folder, copy it.
if (![self.fm fileExistsAtPath:self.destPath]) {
NSString *sourcePath = [[NSBundle mainBundle] pathForResource:#"saves" ofType:#"plist"];
[self.fm copyItemAtPath:sourcePath toPath:self.destPath error:nil];
}
}
- (void)saveBestScore{
NSNumber *bestScoreBox = [NSNumber numberWithUnsignedLong:self.bestScore];
NSDictionary *data = #{bestScoreBox: #"bestScore"};
BOOL successful = [data writeToFile:self.destPath atomically:YES];
successful ? NSLog(#"YES") : NSLog(#"NO");
}
When you say
when I go to look at the plist after, nothing seems to have changed
(the value of bestScore is 0)
Do you mean looking at the plist in xcode project files ? You have copied the plist into a device directory and therefore you wont be able to see the change in xcode.
If you are using simulator, you can access the changed plist at:
~/Library/Application Support/iPhone Simulator/<Simulator Version>/Applications/<application>/Documents/
One easy way of storing score is to use NSUserDefault, which is a dictionary like persistence store for each application.
Set Score:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:#(score)
forKey:#"score"];
[userDefaults synchronize];
Get Score:
int score = [[[NSUserDefaults standardUserDefaults] objectForKey:#"score"] intValue];
UPDATE:
rmaddy mentioned NSUserDefaults supports setInteger:forKey and integerForKey: Therefore you dont need to wrap the score into a NSNumber
When you write an NSDictionary to a plist using writeToFile:, the keys and values in the dictionary must follow strict rules. All keys must be NSString objects and all values must be property values (NSString, NSNumber, NSDate, NSData, etc.).
The problem you have is your dictionary has a key that is an NSNumber, not an NSString.
It appears you actually create the dictionary incorrectly. The syntax is:
#{ key : value, key : value, ... }
Change your code to:
NSDictionary *data = #{ #"bestScore" : bestScoreBox }; // key : value
Side note - your last line should be:
NSLog(#"%#", successful ? #"YES" : #"NO");
It's not good practice to use the ternary operator to run two different commands. It's meant to return one of two values.

How can I add core data to a utility application

Ive made a simple ios utility application in xcode (version 4.4.1) but Ive realised that I need to store one integer in persistent memory. As far as I know using core data is the best way to achieve this.
Ive added the core data framework to my app but I dont know the code that I need to add for it to work.
Could someone please help
Thanks
If you just need to store/retrieve an integer, NSUserDefaults should be the way to go.
Saving
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// saving an NSInteger
[prefs setInteger:42 forKey:#"integerKey"];
// This is suggested to synch prefs, but is not needed (I didn't put it in my tut)
[prefs synchronize];
Retrieving
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// getting an NSInteger
NSInteger myInt = [prefs integerForKey:#"integerKey"];
Reference:
http://www.icodeblog.com/2008/10/03/iphone-programming-tutorial-savingretrieving-data-using-nsuserdefaults/

How do I save user preferences for my iPhone app?

The question title pretty much gives it away - I'd like my app to remember a few things. It's some sort of calculator, so it should save the last used values and some user selectable settings.
Basically I'd like to save a handful of floats and BOOLs and load them again the next time the app loads.
What's the best and easiest way to do that?
Thanks!!
One of the easiest ways would be saving it in the NSUserDefaults:
Setting:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:value
forKey:key];
// – setBool:forKey:
// – setFloat:forKey:
// in your case
[userDefaults synchronize];
Getting:
[[NSUserDefaults standardUserDefaults] objectForKey:key];
– boolForKey:
and
– floatForKey: in your case.
Besides the very good NSUserDefaults approach, there is another easy way to store data from an NSArray,NSDictionary or NSData in a file. You can use these methods as well:
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
respectively (for a NSDictionary):
+ (id)dictionaryWithContentsOfFile:(NSString *)path
you just have to give a valid path to a location. According to the iOS Application Programming Guide, the /Library/Caches directory would be the best place to store data that you need to persist between app launches. (see here)
In order to store/load a dictionary from a filed called "managers" in your document directoy you could use these methods:
-(void) loadDictionary {
//get the documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSCachesDirectory, NSUserDomainMask, YES);
NSString *cacheDirectory = [paths objectAtIndex:0];
//create a destination file name to write the data :
NSString *fullFileName = [NSString stringWithFormat:#"%#/managers", cacheDirectory];
NSDictionary* panelLibraryContent = [NSDictionary dictionaryWithContentsOfFile:fullFileName];
if (panelLibraryContent != nil) {
// load was successful do something with the data...
} else {
// error while loading the file
}
}
-(void) storeDictionary:(NSDictionary*) dictionaryToStore {
//get the documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cacheDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the
//cache directory:
NSString *fullFileName = [NSString stringWithFormat:#"%#/managers", cacheDirectory];
if (dictionaryToStore != nil) {
[dictionaryToStore writeToFile:fullFileName atomically:YES];
}
}
Anyway this approach is very limited and you have to spend a lot of extra work if you want to store more complex data. In that case the CoreData API is very very handy.
In Swift:
Setting
let userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setObject(value, forKey: key)
// userDefaults.setFloat(12.34, forKey: "myFloatKey")
// userDefaults.setBool(true, forKey: "myBoolKey")
Note that for iOS 8 and later, calling userDefaults.synchronize() is not recommended.
Getting
let userDefaults = NSUserDefaults.standardUserDefaults()
if let value = userDefaults.objectForKey(key) {
print(value)
}
Note that userDefaults.boolForKey and userDefaults.floatForKey both return non optional values, so they would never be nil (only false or 0.0).
Further reading
NSUserDefaults — A Swift Introduction
You are looking for NSUserDefaults
Swift 4 / Linux
Apparently something has changed. Now there's the UserDefault class.
Check these links:
https://developer.apple.com/documentation/foundation/userdefaults
https://www.hackingwithswift.com/read/12/2/reading-and-writing-basics-userdefaults

iPhone first time application ran and config files

I'm developing an iPhone application and I want to know when it is the first time the application is executed. I want to check some extended permissions from facebook the first time.
How can I know that?
Another way to solved this problem is to store the extended permissions granted in some configuration file. I don't want to make visible this file through app settings icon.
How can I add some configuration files to store these permissions granted?
The std way would be to check if there is a value in NSUserDefaults and if that value doesn't exist (such as on first run) then create the value so on the rest of the starts you will know its not first run.
This is also a good candidate to use the NSUserDefaults and set key/value pares for each setting/permission you want.
Here's a quick tutorial on using NSUserDefaults.
Summary from that site for Saving:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// saving an NSString
[prefs setObject:#"TextToSave" forKey:#"keyToLookupString"];
// saving an NSInteger
[prefs setInteger:42 forKey:#"integerKey"];
// saving a Double
[prefs setDouble:3.1415 forKey:#"doubleKey"];
// saving a Float
[prefs setFloat:1.2345678 forKey:#"floatKey"];
// This is suggested to synch prefs, but is not needed (I didn't put it in my tut)
[prefs synchronize];
Loading:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// getting an NSString
NSString *myString = [prefs stringForKey:#"keyToLookupString"];
// getting an NSInteger
NSInteger myInt = [prefs integerForKey:#"integerKey"];
// getting an Float
float myFloat = [prefs floatForKey:#"floatKey"];
NSUserDefaults is perfect for saving app settings, and purchase history but if you are wanting to store much data then you should use another way.
Just write to a local file (xml or whatever).
Check, first, for the existence of the file. If not there this is the first run - otherwise just read the file.

Resources