Using NSUserDefaults to store unique order ID - ios

I'm developing a Point of Sale-kind-of-app, which runs on iOS and stores orders and payments in MySQL. I designed the order-table so that there is a client ID and a ClientOrderID which is a combined unique index, preventing duplicate sales.
The iPad gets its Client ID the first time it connects to the server and validates. This means no two iPads will ever get the same Client ID. If they reconnect they get a new one which is from a an auto-increment value of a column in another table designed for this.
Now, the client must of course also have a ClientOrderID to deliver to the server, so that the unique index becomes useful. What I did here is create a static method that looks like:
+(int)getNewOrderOrSaleID {
int orderid = [[NSUserDefaults standardUserDefaults] integerForKey:#"orderid"];
[[NSUserDefaults standardUserDefaults] setInteger:orderid+1 forKey:#"orderid"];
[[NSUserDefaults standardUserDefaults] synchronize];
return orderid;
}
My questions is now this: Is this a reliable method, or does NSUserDefaults tend to mess things up?
And this is probably a bit far out, but doing this every time someone makes an order from the iPad, would that cause wear on the internal storage over time? This question is close to rhetorical, as I do realize how small the data amount is.
As it's only possible to make one order at a time, this method will never run two times at once.

Since you are overwriting the same thing, you won't have new records in the user defaults, the existing one will change. And if you want to persist only some small information (like this int) the user defaults is a good place to do it. However, as Wain mentioned in the comment, the counter will be reset when you reinstall the app.

Related

NSUserDefaults sometimes returns wrong value

I save the user profile picture ID of a user as a string in NSUserDefaults e.g. #"12". When I do that, I call the synchronize method immediately.
When I read this value from NSUserDefaults, it returns #"12" in maybe 99% of the time. But sometimes, it returns a different value (which I cannot find due to the rarity of the event, but suspect it is either nil or some default value (?)).
The code I use to write/read is very simple:
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:#"12" forKey:#"photoID"];
[userDefaults synchronize];
NSString* photoID=[userDefaults objectForKey:#"photoID"];
I know the value sometimes returned is incorrect because the app at the time behaves as if the value was different (i.e. user contacts are notified the profile picture has changed).
And when that happens, the next call to objectForKey returns the correct value, so user contacts received another notification the profile picture has changed again.
NSSynchronize is not guaranteed to succeed and returns a BOOL.
Note that syncrhonize simply writes the data to disk but NSUserDefaults keeps the data in memory as well. Calling it after every write is probably not needed, though I've done it myself and many examples on the net do that.
From the Apple documentation:
use this method only if you cannot wait for the automatic synchronization (for example, if your application is about to exit) or if you want to update the user defaults to what is on disk even though you have not made any changes.
Disclaimer: speculation
It's possible that the act of failed synchronize is causing objectForKey to fail. The class knows the data it has may be wrong and so returns nil instead. This is more likely if you are calling synchronize successively and excessively or otherwise doing IO intensive operations.

IOS - Storing value in a Static Variable like php Sessions

I have an app that needs to keep hold of how many people have joined a room, my problem is keeping a hold of this value. I need to increment this value by one every time the user joins. So i need to check that the room is not full.
I have been thinking of using sessions and keeping track of this value in php, but is there another way natively, so my question is how do i retain or persist this value?
I tried this running on two phones but the value is always 1 when the global value (myData) should be 2 when the second phone runs the app:
myData = myData + 1;
[[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:#"%d", myData] forKey:#"myData"];
NSLog(#"%d",myData);
If you want to synchronise information between the devices in your case, you should update the data using your server (or how you handle the networking between the devices and rooms etc.)
For example if you install the app in a new phone, it should firstly fetch the value from your server and save the NSUserDefaults so that it can be synchronised.
However, with this way, I don't think you need to store data in the phone, so you can directly use information from server to check the room fullness etc. Storing as NSUserDefaults looked unnecessary to me.
I hope I got the question and your app right.

Collect user input from UITextField and storing it in a certain place - Xcode

I can't figure out how to make the create an account function work in my application... I have my login system set up like so: http://imgur.com/dKGRnok The first set of strings are the passwords. The second set are the usernames. For someone to create an account that allows them to login, I have to make a string manually through the application. How can I make this function so it gets their input and places it as a string as long as the same username doesn't already exist? http://imgur.com/lVzAV8i
You need to create a local database, the proper way would be to use either sqllite or core data to create your structure, then simply add/remove users.
For an sql tutorial for ios follow this:
http://www.raywenderlich.com/913/sqlite-tutorial-for-ios-making-our-app
Or go to this site and check the section that says "Saving and Loading Data"
http://www.raywenderlich.com/tutorials
I personally prefer core data because its the most complete solution once you get used to setting it up.
If what you are asking is a persistent data, [[NSUserDefaults standardUserDefaults] setValue: forKey:] will be the answer.
Once you save a data with NSUserDefaults, the data will be persistent. You can get the value with [[NSUserDefaults standardUserDefaults] valueForKey:]
Added
I misunderstood your question. In this case you should use local database as Chiques said.
Core Data will be the answer.
http://www.raywenderlich.com/934/core-data-tutorial-for-ios-getting-started

Is it ok to read a value stored in NSUserDefaults in multiple views

Is it ok to read a value stored in NSUserDefaults from multiple views or you only read it once and then you use another method to pass the data to different part of your app?
In other words I want to know if I’m doing it right, what I’m currently doing in an app I’m working on is basically saving a couple of NSIntegers and NSStrings (only two or three of each) in NSUserDefaults and then I’m reading those values in different parts of my app (different views) but I was wondering if this is a common practice or should I be doing something different like, read the value somewhere in the app and then try to use a different method to pass that data to other views. I want to learn best programming practices, that’s all.
What is the most common practice when using NSUserDefaults values in multiple parts of your app?
FYI,
I’m familiar with multiple ways to pass data between view controllers such as, delegation, prepareForSegue etc.
Thanks a lot.
I would also recommend, to read it multiple times and do not introduce another layer to hold the data.
The most important aspect is imo the actuality of the data, which might be changed inbetween different invocations.
It is ok to read and even write values to NSUserDefault in multiple places, but it is a better practice to have a global mechanism (like a singleton pattern) to read and write to UserDefaults. this way you'll be guaranteed to have fully synchronized values. all you need to do is to create a new class and add a few Class methods to read and write values from NSUserDefaults.
It is OK, when you call [NSUserDefaults standardUserDefaults] it will return the same object whether you spread the calls everywhere in the app or you encapsulate the access in a class.
I prefer the later as it allows you to have more readable code (and other benefits):
BOOL hasX = [TLPSettings hasPreferenceX];
if (hasX) {
[TLPSettings setY:YES];
}
vs
BOOL hasX = [[NSUserDefaults standardUserDefaults] boolForKey:#"hasX"];
if (hasX) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"hasY"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
You can change the preferences keys easily (without defining consts for them), change the validation or logic of a preference without messing with it everywhere, debug its usage or rogue values easily, store all or part of them in a different place, etc.
TLP is your three letter prefix.

Best way to store user information for my iOS app

What kind of database do you suggest? I want to store user email, username, password, and a couple other random pieces of information. It doesn't have to be fancy. Just a simple database. Are there any free options?
The user information needs to be stored in the keychain to keep it secure.
Any other information could be stored in any one of:
User defaults NSUserDefaults
File on disk (maybe a plist)
Database Core Data (technically just a file on disk)
Which you choose depends on what the data is, how much there is and what kind of access you need to it.
If your data is small and chosen by the user as some kind of setting then user defaults makes sense and is the lowest cost for you to implement.
To use a database, check out Core Data intro.
Wain is right but I think as you want to store small amount of data for further use, the most efficient ways is to use NSUserDefault.
NSUserDefault stores data in NSDictionary type things.
I think this is the step you have to take:
1- check if data exists. I mean if user selected the number if the last run of your app. So in viewDidLoad method:
NSMutableDictionary *userDefaultDataDictionary = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:ALL_DATA_KEY] mutableCopy];
if (userDefaultDataDictionary) {
// so the dictionary exists, which means user has entered the number in previous app run
// and you can read it from the NSDictionaty:
if(userDefaultDataDictionary[LABLE_KEY]){
//and store it
}
}
2 - you can implement some method like syncronize to store data in NSUserDefault every time something has been changed.
- (void) synchronize
{
NSMutableDictionary *dictionaryForUserDefault = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:ALL_DATA_KEY] mutableCopy];
if(!dictionaryForUserDefault)
dictionaryForUserDefault = [[NSMutableDictionary alloc] init];
dictionaryForUserDefault[LABLE_KEY] = //data you want to store
[[NSUserDefaults standardUserDefaults] setObject:dictionaryForUserDefault forKey:ALL_DATA_KEY];
[[NSUserDefaults standardUserDefaults] synchronize];
}
P.S. and don't forget to #define your keys for your dictionary:
#define LABLE_KEY #"Lables"
#define ALL_DATA_KEY #"AllData"
Store it in a plist. If you're talking about data pertaining to one or a few users, that's probably the easy thing. here is a simple example.
Since you say database, store in Sqlite. There's some provided stuff for it already in xcode.
The entire database is contained in one file, which can be moved around if you need to.
Here is some more information on how to use one in your app.

Resources