I placed a BOOL inside a UIButton. If I click on the Button once, then I want that BOOL to always be saved so I never has to click on button again while in the game. I used the following code but it doesn't work to save. However, the code should work. It's mainly the final line of code that makes the saving not work. What am I doing wrong?
-(void)viewDidLoad{
[[NSUserDefaults standardUserDefaults] setBool:REDguy forKey:#"save"];
if (REDguy==[[NSUserDefaults standardUserDefaults]synchronize]) {
MAN.image=[UIImage imageNamed:#"RED.png"];
}
REDguy=[[NSUserDefaults standardUserDefaults]boolForKey:#"save"];
}
EDIT:
if (REDguy==YES) {
[[NSUserDefaults standardUserDefaults] setBool:REDguy forKey:#"save"];
REDguy =[[NSUserDefaults standardUserDefaults]boolForKey:#"save"];
MAN.image=[UIImage imageNamed:#"RED.png"];
}
This is an assumption since you didn't really clarify what else is going on in your code, but it looks like your bool REDGuy is always going to be be NO on viewDidLoad, and that if condition is likely to always be false since synchronize will probably always be YES (not to mention, that comparison makes no sense and it's rarely necessary to call synchronize since synchronization with user defaults happens on its own).
A simple way to determine if a button has been pressed before is to add the following to your button action method.
- (void)buttonAction:(id)sender {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"save"];
}
- (void)viewDidLoad {
BOOL hasSaved = [[NSUserDefaults standardUserDefaults] boolForKey:#"save"];
if (hasSaved) {
// You can hide your button here if that's what you're going for
[yourButton setHidden:YES]
}
}
Is that what you are trying to accomplish? Determining if a specific button has been tapped before?
Related
I know this has been asked before but I have yet to find a solution to this. I am attempting to save UISwitch state so that no matter which VC I enter, that switch state is still active. However, anytime I leave the VC the switch is in, it's resorts to off. Currently this is the code I'm using to save the switch state:
- (IBAction)tvpSwitch:(UISwitch *)sender {
if (sender.isOn) {
[[NSUserDefaults standardUserDefaults]setObject:#"on" forKey:#"tvpSwitch"];
[[NSUserDefaults standardUserDefaults]synchronize];
}
else {
[[NSUserDefaults standardUserDefaults]setObject:#"off" forKey:#"tvpSwitch"];
[[NSUserDefaults standardUserDefaults]synchronize];
}}
I then put this is any VC viewWillAppear:
-(void)viewWillAppear:(BOOL)animated
{
if ([[[NSUserDefaults standardUserDefaults]valueForKey:#"tvpSwitch"]isEqualToString:#"on"])
{
(sender.isOn=YES);
}
else
{
(sender.isOn=NO);
}}
It also flags in the viewWillAppear method that reads: "Use of undeclared identifier 'sender'."I usually try using the Reference Guide but I'm having a difficult time identifying where this is going wrong. Any help would be great! Thanks!
Like you have an IBAction there, I suppose you created the UISwitch trough Interface Builder. If that's the case, create an IBOutlet from the UISwitch and then always reference to it.
In the first code snippet sender is the parameter passed in the IBAction method which is a reference to the UISwitch.
In the other view controllers you need some reference to that UISwitch but if you want only to check that state without being able to change it in the UI, just get it from NSUserDefaults and use it.
By the way there are designated methods of NSUserDefaults for saving a BOOL type.
- (IBAction)tvpSwitch:(UISwitch *)sender {
[[NSUserDefaults standardUserDefaults] setBool:sender.isOn forKey:#"tvpSwitch"];
}
BOOL switchState;
-(void)viewWillAppear:(BOOL)animated
{
switchState = [[NSUserDefaults standardUserDefaults] boolForKey:#"tvpSwitch"];
// do something with switchState
}
For instance, I want a logon screen in ViewController1 to be displayed if the app is launched for the first time. If the app is not launched for the first time or the user has already logged in, it will just start from ViewController2. How do I implement this?
Try this link: Check for first launch of my application
The best code for this link was done by Omar, in my opinion. But there are a few great answers on there, as well as one answer with good philosophy on the matter. If you want a small explanation on how to run the code and understand it yourself, NSGod has a good code snippet for you.
If that doesn't help, try this link: How to setup first time launch of an iOS App
ALSO, Here's some code I whipped up for you . . .
- (BOOL)isFirstTimeLaunching {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults integerForKey:#"hasRun"] == 0) {
// Do some first-launch code...
[defaults setInteger:1 forKey:#"hasRun"];
[defaults synchronize];
return YES;
}
return NO;
}
Remember, returning 0 is returning true. Returning anything other than 0 is returning false. When the app hasn't been run yet, the key #"hasRun" will be false, and will return 0. Once it's been run, reset it back to 0 to prevent the first-launch code from running again.
I would use NSUserDefaults. In the AppDelegate.m do something like:
if(![[NSUserDefaults standardDefaults] objectForKey:#"shouldLaunchSignUp"]){
//launch your sign up view controller here
//set the user default to yes
[[NSUserDefaults standardDefaults] setBool:YES forKey:#"shouldLanuchSignUp"];
}
check in viewDidLoad and set a boolean flag.
- (BOOL)isFirstTimeLaunching {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults integerForKey:#"hasRun"] == 0) {
// Do some first-launch code...
[defaults setInteger:1 forKey:#"hasRun"];
[defaults synchronize];
return YES;
}
return NO;
}
And in viewDidAppear, on basis of flag present your log in view.
Remember , in viewDidLoad you can't present another view.
My UISegmentedControl will not stay selected. I have made sure that momentary is NO. So the solutions I have come across on here have not helped.
Would someone please be able to point me in the right direction?
EDIT
Thought I might make this question a bit clearer.
I have a UISegmentedControl and it has four selections (10,20,30,40) which changes the amount of questions asked on my quiz page. Making a selection works fine and changes the amount of questions.
But when I leave that view and go back later on to change the amount of questions again, it shows the selected as 10 even if I have selected something else.
How can I keep it showing the actual selected value?
EDIT
The number of questions is saved in NSUserDefaults.
[[NSUserDefaults standardUserDefaults] setInteger:amountOfQuestions forKey:#"Amount"]
How do I initialize a segmented control with a value from NSUserDefaults?
EDIT - Solved
#SettingsViewController .m file.
- (void)viewDidLoad
{
amountOfQuestions = [[NSUserDefaults standardUserDefaults] integerForKey:#"Amount"];
if (amountOfQuestions == 10) {
mySegment.selectedSegmentIndex = 0;
}
I did not have the below code in my IBAction for my segmented control. So when i tried the above code it did not work. Now it works a treat.
[[NSUserDefaults standardUserDefaults]synchronize];
#SettingsViewController .m file.
- (void)viewDidLoad
{
amountOfQuestions = [[NSUserDefaults standardUserDefaults] integerForKey:#"Amount"];
if (amountOfQuestions == 10) {
mySegment.selectedSegmentIndex = 0;
}
I did not have the below code in my IBAction for my segmented control. So when i tried the above code it did not work. Now it works a treat.
[[NSUserDefaults standardUserDefaults]synchronize];
I want to show a help overlay when a user runs my application for the first time.
To do this, I'm using the following code indidFinishLaunching:
if(![[[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] allKeys] containsObject:#"IPHONEFIRSTRUN"])
[[NSUserDefaults standardUserDefaults]setBool:TRUE forKey:#"IPHONEFIRSTRUN"];
In the view controller, I have:
if ([[NSUserDefaults standardUserDefaults]boolForKey:#"IPHONEFIRSTRUN"]==TRUE) {
[self HelpOverlayIphone];
[[NSUserDefaults standardUserDefaults]setBool:FALSE forKey:#"IPHONEFIRSTRUN"];
}
However, it shows the overlay on the second use as well. How can I fix this? Any help is appreciated.
Your logic is overly complex. You are setting permanently a user default to indicate something happening one time. Instead, in the view controller see if the value is not set, if it is do your action and set the variable so that the code is NOT run again:
if ( ! [[NSUserDefaults standardUserDefaults]boolForKey:#"IPHONEFIRSTRUNCOMPLETE"] ) {
[self HelpOverlayIphone];
[[NSUserDefaults standardUserDefaults]setBool:YES forKey:#"IPHONEFIRSTRUNCOMPLETE"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Take out all the code in the app delegate.
Also it's very likely your original code is not working because you are stopping the app from XCode. If you don't use synchronize user default changes will not be saved in that case (normal quitting of the app does eventually save the changes permanently).
Have you registered the defaults you are using at the start of the program? I would suggest rereading the apple documentation for NSUserDefaults here
You need to first make a call to
- (void)registerDefaults:(NSDictionary *)dictionary
which will only set the key if it doesn't already exist. Then check the key for falseness on the the first run and set it at this point.
My guess is the reason your code isn't working is because the dictionary is never actually being saved in any sort of persistent way.
I have this function which fires when the app fires up- it's always been reliable. I have a uniqueNameOfApp which is just some random hash so that it doesn't collide with other apps.
-(void)loadSettings {
NSMutableDictionary *sttngs = [[NSUserDefaults standardUserDefaults]
objectForKey:uniqueNameOfApp];
if(sttngs != nil) {
[userSettings addEntriesFromDictionary:sttngs];
} else {
_appFiredForFirstTime = YES;
}
}
I am using NSUSerDefaults to store a couple strings and integers for my application. Whenever a view is opened, the string is loaded slower than the view so you see a glitch. For example, I save the selectedSegmentIndex and then read it in viewDidAppear and for a quick moment when the view is called, no segment is selected, then the right one selects. How do you make it so there is no time gap between the view being opened and the setting be read?
- (void)viewDidLoad
{
[super viewDidLoad];
int segmentIndex = [[NSUserDefaults standardUserDefaults] integerForKey:#"selectedIndex"];
unitSegmentControl.selectedSegmentIndex = segmentIndex;
BOOL location = [[NSUserDefaults standardUserDefaults] boolForKey:#"locationManager"];
[gpsSwitch setOn:location animated:NO];
deviceID.text = [[NSUserDefaults standardUserDefaults] stringForKey:#"DeviceID"];
}
- (IBAction)changeSeg:(id)sender {
if (unitSegmentControl.selectedSegmentIndex == 0) {
[[NSUserDefaults standardUserDefaults] setObject:#"http://98.246.50.81/firecom/xml/units/E01.xml" forKey:#"parserURL"];
[[NSUserDefaults standardUserDefaults] setObject:#"Hillsboro Main" forKey:#"selectedStation"];
[[NSUserDefaults standardUserDefaults] setObject:#"Hillsboro Fire & Rescue" forKey:#"selectedDepartment"];
}
if (unitSegmentControl.selectedSegmentIndex == 1) {
[[NSUserDefaults standardUserDefaults] setObject:#"http://98.246.50.81/firecom/xml/units/E02.xml" forKey:#"parserURL"];
[[NSUserDefaults standardUserDefaults] setObject:#"Hillsboro Witch Hazel" forKey:#"selectedStation"];
[[NSUserDefaults standardUserDefaults] setObject:#"Hillsboro Fire & Rescue" forKey:#"selectedDepartment"];
}
[[NSUserDefaults standardUserDefaults] setInteger:unitSegmentControl.selectedSegmentIndex forKey:#"selectedIndex"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
The defaults are not slow, you’re just loading the data too late. The standard place to populate views is in -viewDidLoad or -viewWillAppear in the view’s controller. Both will update the view soon enough to avoid visual glitches. If any of the two doesn’t work for you, here’s some tips to find the reason:
Try to set the selected index to a hard-wired number. This will tell you if the problem is in the defaults or (much more likely) in the -setSelectedSegmentIndex call.
Move the UI population code to -viewWillAppear. That’s the latest moment to update the UI before it’s displayed.
Use NSParameterAssert to make sure unitSegmentControl is not nil.
Make sure the index read back from the defaults is the expected number. Generally, it’s best to pull the defaults keys into constants. That way you can’t bump into simple typo bugs:
static NSString *const SelectedSegmentKey = #"selectedSegment";
If everything else fails, use a custom UISegmentControl subclass for your unitSegmentControl and place a breakpoint into -setSelectedSegmentIndex to see who else might be calling it.