NSUserDefaults problem - iphone

I have this in my app delegate applicationDidFinishLaunching method:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults objectForKey:#"AcceptTC"] == nil){
NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:#"NO" forKey:#"AcceptTC"];
[defaults registerDefaults:appDefaults];
}
and I have this in my RootViewController viewDidLoad method:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if(![defaults boolForKey:#"AcceptTC"]){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Notice" message:#"By using this application you agree to be bound by the Terms and Conditions as stated within this application." delegate:self cancelButtonTitle:#"No Deal" otherButtonTitles:#"I Understand",nil];
[alert show];
[alert release];
}
and my alert view delegate does this:
if(buttonIndex == 0){
exit(0);
}
else{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:#"YES" forKey:#"AcceptTC"];
}
However when I click "I understand" (button index 1) and then restart the application I still see the alert view! Even though I've definiely set the value to YES.
I have no idea how to change this. :( I only want it to show the first time a user starts the application - i don't want to keep showing it every time they want to use it.
Thanks

In my application I'm using NSUserDefaults with a bool, works fine.
When the first ViewController loads, it will do:
BOOL terms = [[NSUserDefaults standardUserDefaults] boolForKey:#"termsaccepted"];
if (!terms) {
[self presentModalViewController:disclaimerViewController animated:YES];
}
Within the disclaimer view, after the button has been tapped:
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"termsaccepted"];
[[NSUserDefaults standardUserDefaults] synchronize];
I think you're missing the "synchronize" part. However I find using a bool more streamlined, too.

Maybe you need to call synchronize on the defaults to save the changes to disk?

Concering registerDefaults:
The contents of the registration domain are not written to disk; you need to call this method each time your application starts. You can place a plist file in the application's Resources directory and call registerDefaults: with the contents that you read in from that file.
// Load default defaults
[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary \
dictionaryWithContentsOfFile:[[NSBundle mainBundle] \
pathForResource:#"Defaults" ofType:#"plist"]]];
Code taken from this SO answer.
Another blog article about NSDefaults:
http://retrodreamer.com/blog/2010/07/slight-change-of-plan/

Related

NSUserDefaults, saving data issue

So I have an app that lets you put in a title and an author on the front page, then you hit enter and it will go into the actual features of the app. I want to save the data with NSUserDefaults, so that when they click the enter button, it saves it *AND goes into the next view. I have it setup with the storybord already to go into the next view, but when I use this code:
-(IBAction)enter:(id)sender {
titleString = [[NSString alloc] initWithFormat:[title text]];
[title setText:titleString];
NSUserDefaults *titleDefault = [NSUserDefaults standardUserDefaults];
[titleDefault setObject:titleString forKey:#"stringkey"];
authorString = [[NSString alloc] initWithFormat:[author text]];
[title setText:authorString];
NSUserDefaults *authorDefault = [NSUserDefaults standardUserDefaults];
[authorDefault setObject:authorString forKey:#"stringkey2"];
}
It will always crash when you hit the button. I have all the NSStrings defined and such, so I don't see what the problem is. I also have it loading with:
title.text = [[NSUserDefaults standardUserDefaults] objectForKey:#"stringkey"];
author.text = [[NSUserDefaults standardUserDefaults] objectForKey:#"stringkey2"];
Under the viewdidload, so can I have some help as to why this wouldn't work?
Just to optimize your -enter:method:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:title.text forKey:#"stringkey"];
[defaults setObject:author.text forKey:#"stringkey2"];
[defaults synchronize]; // this will store them instantly!
For the crash: can you please provide us with the exact crash log? Maybe your Button is linked to an unknown selector...
First, there are a few questions about this: here, here. Try searching around first, and at least let people know why the duplicate questions you found didn't work for you.
Secondly, I think you might benefit from adding a synchronize. Use this:
titleString = [[NSString alloc] initWithFormat:[title text]];
[title setText:titleString];
NSUserDefaults *titleDefault = [NSUserDefaults standardUserDefaults];
[titleDefault setObject:titleString forKey:#"stringkey"];
[titleDefault synchronize];
authorString = [[NSString alloc] initWithFormat:[author text]];
[author setText:authorString];
NSUserDefaults *authorDefault = [NSUserDefaults standardUserDefaults];
[authorDefault setObject:authorString forKey:#"stringkey2"];
[authorDefault synchronize];
I also changed the [title setText:authorString]; line to [author setText:authorString];. I do, however, think it is a bit redundant the way you are allocating the NSStrings to the value of the text fields and then setting the text back to the value of the string you created. I don't get the need. Anyway, hope this helps.

How to Show popup Alert view when apps run first time?

Everyone, I'm working in iphone. I've a problem that I want to show a alert view popup when my apps run first time in iphone. I'm not getting how to do this. Please someone help me.
BOOL foo = [[NSUserDefaults standardUserDefaults]boolForKey:#"previouslyLaunched"];
if (!foo)
{
NSLog(#"FirstLaunch");
[[NSUserDefaults standardUserDefaults]setBool:YES forKey:#"previouslyLaunched"];
}
Edit: What Akshay said earlier, with some code.
3 simple lines
-(BOOL)application:(UIApplication *)application … {
if(![[[NSUserDefaults standardUserDefaults] objectForKey:#"NOT_FIRST_TIME"] boolValue])
{
[[[[UIAlertView alloc] initWithTitle:nil message:#"message" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil] autorelease] show];
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:#"NOT_FIRST_TIME"];
}
}
You will probably need to store some data on first run of the application (like current date). Every time the application starts you will check for this data and if it doesn't exist store it and display the popup.
Put the alertview code in didFinishLaunchingWithOptions function in delegate.m
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults objectForKey:#"FirstTime"] == nil)
{
//your alert message
}
[defaults setObject:#"firsttime" forKey:#"FirstTime"];
Save a BOOL value using NSUserDefaults which corresponds to whether it is the application's first launch. If you find the boolean to be YES (or don't find the value), display the alert and set the value to NO.

How To Connect NSUserDefaults To UISwitch?

So I have setup my settings bundle which works in the iPhone's settings app. I want to add one of the settings within my own app. I know I can use InAppSettings framework, but I just want to add one settings, not all of them, and I already have an page ready that I want to add this settings option to.
So I have replicated the cell with UISwitch in my app which looks the same as the settings one. My question is, how can I now connect this UISwitch to my NSUserDefaults so it functions as a settings UISwitch?
In my appDelegate, I have:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:#"No" forKey:#"isKgs"];
[defaults registerDefaults:appDefaults];
[defaults synchronize];
Edit - All related code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:NO forKey: #"isKgs"];
[defaults synchronize];
}
The cell inside the app where I want the UISwitch to be
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UISwitch *switchView = [[UISwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = switchView;
[switchView addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
[switchView setOn:[[NSUserDefaults standardUserDefaults] boolForKey:#"isKgs"] animated:NO];
[switchView release];
}
And the settings bundle where I have the same UISwitch that can be acceded through iPhone settings app:
Edit 2:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (nil == [defaults objectForKey:#"isKgs"])
{
[defaults setBool:NO forKey: #"isKgs"];
}
else
{
}
[defaults synchronize];
It's easier to use a boolean variable if you want to use a UISwitch. In the app delegate, set the default value for the settings, if not existed:
// set the default settings
NSString *testValue = [[NSUserDefaults standardUserDefaults] stringForKey:#"testSwitch"];
if (!testValue) {
// since no default values have been set, create them here
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"testSwitch"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
And then create use the value from the NSUserDefaults settings to turn on the switch if needed:
UISwitch* testSwitch = [[[UISwitch alloc] init] autorelease];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"testSwitch"]) {
[testSwitch setOn:YES animated:NO];
}
You should head aporat's suggestion and use a BOOL instead. However, if you are insistent on using a string as in your question, then you will have to do this:
if ([[[NSUserDefaults standardUserDefaults] objectForKey:#"isKgs"] isEqualToString:#"No") {
[switch setOn:NO animated:NO];
}
However, if you use a BOOL, you can set the switch in one simple line:
[switch setOn:[[NSUserDefaults standardUserDefaults] boolForKey:#"isKgs"] animated:NO];
This means that you must go back and set up the defaults like this:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:NO forKey#"isKgs"];
[defaults synchronize];
At some point in your code you are going to have to check the switch state and write it back to userDefaults:
[[NSUserDefaults standardUserDefaults] setBool:[switch on] forKey:#"isKgsk"];
[defaults synchronize];
you can write the changes back to userDefaults in your switchChanged: function.
Also, if you always set your key to NO in didFinishLaunchingWithOptions: then it will never reflect changes made in the settings app, it will always be NO.... this is probably not what you want.

Saving and Retrieving UILabel value with NSUserDefaults

I trying to save UILabel value to NSUserDefaults. I did IBAction with this code:
-(IBAction)saveData:(id)sender {
NSString *resultString = label.text;
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:resultString forKey:#"result"];
[prefs synchronize];
}
Then, I connect it to button with Touch Up Inside.
What log shows after I pressed the button:
result = 0;
When I pressed a second time, then it works.
result = "28.34";
What I'm doing wrong and how can I retrieve a result?
EDIT
With this code I display result in log. I put it to same action.
NSLog(#"%#", [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]);
Your code looks correct, so the issue is probably not the function you posted but rather the code that contains your NSLog. You might be logging the value in a way that misses the first time it gets set.
Your log statement should be
NSLog(#"%#",[[NSUserDefaults
standardUserDefaults]
objectForKey:#"result"]);
This should be after you set the object in NSUserDefaults.
Add this to your applicationDidFinishLaunching in appDelegate or in init method in viewController(you have to create one) :
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if(prefs == nil)
{
[prefs setObject:#"anything" forKey:#"result"];
[prefs synchronize];
}

Can I change the apps view based on if a file has been saved?

Please help! I'm a newbie to programming and I'm having the following trouble. I am trying to write my first iphone app and I would like it to do the following.
When the app launches user enters name, presses button and goes to new view. Their name is saved to file and used through out the app. That much I have managed.
I would like the app to check to see if there is a saved file when it is launched and go directly to second view instead of the first view. I'm have search for days looking for an answer and I'm still not sure how to do this.
At the risk of seeming stupid do I use an IF statement and how do I write it. Please help.
Thanking you in advance.
You have to use NSUserDefaults for storing the user name and pass words. If you want to store more data's, have to use plist(Documents Directory) or core data or SQLite.
// Store the data
[[NSUserDefaults standardUserDefaults] setObject:#"yourPasswordString" forKey:#"YourKey"];
// Retrieve the data
NSString *passWord = [[NSUserDefaults standardUserDefaults] objectForKey:#"YourKey"];
Once you retrieved the data, you have to check the conditions like,
if(passWord == nil)
{
//load first view
}
else
{
// load second view
}
Thanks!
if you're using NSUserDefaults to save it then all you have to do is try reading the value into a string, then check if it is nil, if it is, then the files isn't there and you would load your first view, if it was, then load your second view.
NSString *tempStr = [[NSUserDefaults standardUserDefaults] objectForKey:#"yourKey"];
if(tempStr == nil)
{
//load your first view
}
else
{
// load your second view
}
You need to read your key back out in order to test if it is nil, the way you are doing this, you will never be nil and will always use the else choice, you need to set your object elsewhere, probably in the if statement.
-(IBAction)LogInButton:(id)sender
{
NSString *tempStr = [[NSUserDefaults standardUserDefaults] objectForKey:#"UserName"];
if (tempStr == nil || [tempStr isEqualToString:""])
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:Name.text forKey:#"UserName"];
[prefs synchronize];
ClubSearchViewController *CSearch = [[ClubSearchViewController alloc]initWithNibName:#"ClubSearchViewController" bundle:Nil];
[self presentModalViewController:CSearch animated:YES];
}
else
{
SearchMenu *SMenu = [[SearchMenu alloc]initWithNibName:#"SearchMenu" bundle:nil];
[self presentModalViewController:SMenu animated:YES];
}
}
-(IBAction)LogOutButton:(id)sender
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:#"" forKey:#"UserName"];
[prefs synchronize];
}