I am trying to save/load some data for my game (in this case, the # of tips the player has available to them). If they are playing the game for the first time, they get 10 tips to start with, otherwise, it will load the number of tips they had before they last quit the game. My issue is that when starting the game for the first time, I am setting the number of tips to 10 but the UILabel is displaying 0.
These here are my save and load methods:
- (void)saveSettings
{
NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
[settings setInteger:self.tipCount forKey:#"tipCount"];
}
- (void)loadSettings
{
NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
if (![settings boolForKey:#"userDefaultsSet"])
{
[settings setBool:1 forKey:#"userDefaultsSet"];
[settings setInteger:10 forKey:#"tipCount"];
self.tipCount = 10;
} else {
self.tipCount = [settings integerForKey:#"tipCount"];
}
}
And this here is how I am updating my label:
- (void)updateLabel
{
Quiz* sharedQuiz = [Quiz sharedInstance];
self.statusLabel.text = [NSString stringWithFormat:#"Tips Remaining: %d", [sharedQuiz tipCount]];
}
Any help that can point me in the right direction is appreciated. Thanks in advance!
Here i would like add few things to your question as precautions, it might be so, you already have been taken that care but still i am trying to say you see below.
Check whether you are calling loadSetting method Before calling any other method (saveSettings method and updateLabel method) by which you want to display some information.look you have not set any value to tips count besides from that single method(loadSetting) if that method not caling it means you are getting this 0 number on UILabel.so you should take care of this single thing whether you have properly called loadSetting method before showing the tips count to the user over the UILabbel.since after looking into your code it seems u that you did everything in correct way as you should have done.
You can check this out but setting some break point at required place and check out the main reason behind it.
I hope it may helps you and could give any idea so that you can get some help form above
Related
I created my iMessage extension, when I try to open it, the first screen appears but it is totally frozen, and it does not react in any way.
I've put logs in the viewDidLoad of that first view and nothing appears there, after a few seconds I can already see those logs.
To make the application freezing lose that status, user has to slide screen left or right and back again.
I've tried looking all over the web for someone who happens to be the same, but I could not find anything.
It does not come to mind more screenshots or portions of code add, if you think I should provide some additional information, just let me know
Any help would be appreciated.
Thank you.
UPDATE:
This is my Project Structure.
This is my viewDidLoad code.
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"here viewDidLoad iMessage ext~~~!");
[self applyCornerRadiusToBtn];
[self registerPresentationAction];
NSDictionary *user = [self getUserInfoFromHostApp];
if (user) {
NSLog(#"Here != null user info");
//It is assumed that when you enter this point and run this log, the app should navigate to the next screen, but it does not.
[self performSegueWithIdentifier:#"goToYoutubeListIm" sender:nil];
} else {
NSLog(#"Here userInfo null");
}
}
- (NSDictionary *)getUserInfoFromHostApp
{
NSUserDefaults *myDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.com.xxxxx"];
NSDictionary *userNameSaved = [myDefaults objectForKey:#"userInfoExt"];;
NSLog(#"userNameSaved in xxxx Ext ==> %#",userNameSaved);
NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:#"group.com.xxxx"];
NSLog(#"groupURL ==> %#",groupURL);
return userNameSaved;
}
For all concerned I have found the problem or problems to be accurate.
1) I was creating my controllers type MSMessagesAppViewController. Apparently there should only be one controller of this type.
2) I had logic in the viewDidAppear in my MSMessagesAppViewController. For some strange reason this also caused the problem, I had to get the logic out there and force the user to interact with a button to execute the logic that was in the didAppear
I am having a IBAction for 4 buttons which represent 4 available answers and each time I press a button I read the sender ID, then it figures out if answer is correct and so on.
Now I have a special case, when another button (nothing in common with those 4 buttons) is pressed, it waits for two of these answers, checks if one of them is correct( i know how to do that) and then the program continues running.
So for now, I have :
- (IBAction)answerButtonPressed:(id)sender {
NSString* answer= [[sender titleLabel] text];
//checks if answer key is equal to a1 ( which is always the correct answer )
if([[currentQuestionUsefulVariable valueForKey:#"a1"] isEqualToString:answer] ){
correctQuestionsCount1 ++;
}
//answer is wrong
else{
wrongQuestionsCount1 ++;
}
}
As you see I store the answer string in a variable called answer
And again - All I need is to store two answers and check the two of them when this special button is pressed. I will of course put a boolean variable to indicate when it is pressed and it will do the work.
EDIT:
The two answer thing is when I press a specific joker button and it gives the advantage to the user to chose two of four available answers. This is why I need to do that. For any other cases I need only one answer at a time.
Any ideas ?
Well you're going to need an instance variable, the value of which persists throughout the lifetime of the object, and perhaps using a mutable array of the answers is the way forward:
#interface MyViewController ()
{
NSMutableArray *_correctAnswers;
}
It must be initialised in viewDidLoad (other options are available):
-(void)viewDidLoad {
[super viewDidLoad];
_correctAnswers = [NSMutableArray new];
}
and then start collecting correct answers into this array:
- (IBAction)answerButtonPressed:(id)sender {
NSString* answer= [[sender titleLabel] text];
//checks if answer key is equal to a1 ( which is always the correct answer )
if([[currentQuestionUsefulVariable valueForKey:#"a1"] isEqualToString:answer] ){
[_correctAnswers addObject:answer];
}
//answer is wrong
else{
wrongQuestionsCount1 ++;
}
if ([_correctAnswers count] == 2) {
// Do something? It's not exactly clear what you want to do
// when 2 correct answers have been given.
}
}
Note: you can dump correctQuestionsCount1 as that will be [_correctAnswers count] now. Also you will need to reset the array at some point.
Note 2: You could also start collecting incorrect answers as well, for some analysis or perhaps to disable that button so the user cannot repeatedly answer the question wrong.
I am pretty new to iOS so here's my question. I have a Table View (GuestTableViewController) listing some guests in a party. When I click in a person, I show a new view (GuestInfoViewController) with some info about this attendee. In this view I have switch button, so if I have 3 persons, there will be 3 switches indicating each one of them is coming or not.
Using NSUserDefaults in a IBAction in my GuestInfoViewController I have achieved to save its state (ON/OFF) between views.
The problem is that when I click one switch, all switches change state. How can reference each one of the switches.
Note: I can post images on my storyboard or even some code if needed.
Thank you so very much!
#implementation GuestInfoViewController
#synthesize nom,cognoms,foto;
#synthesize setNom,setCognoms,setFoto;
#synthesize mySwitch;
- (void)viewDidLoad
{
[super viewDidLoad];
nom.text = setNom;
cognoms.text = setCognoms;
[foto setImage:[UIImage imageNamed:setFoto]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"SwitchState"])
self.mySwitch.on = [defaults boolForKey:#"SwitchState"];
}
- (IBAction)switch:(id)sender {
if(mySwitch.on){
NSLog(#"Switch is ON");
}
if(!mySwitch.on){
NSLog(#"Switch is OFF");
}
}
- (IBAction)saveSwitchState:(id)sender
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([self.mySwitch isOn])
[defaults setBool:YES forKey:#"SwitchState"];
else
[defaults setBool:NO forKey:#"SwitchState"];
}
#end
Your code uses the same key for all the attendees - that is what you should take care of.
Since you obviously set the name and surname for each person (and if we presume that two attendees don't have the same name) you could use this to your advantage.
Change all the #"SwitchState" references
to something like
[NSString stringWithFormat:#"SwitchState_%#_%#",setNom,setCognoms]
This would effectively save the state of the switches for each attendee separately.
Using you're line of thinking, you would need to store 3 keys in NSUserDefaults, one for each person. It would be a mess to use it, for instance, if you have 1000 persons.
I believe the proper way to implement this is by using a Delegate on your GuestInfoViewController.
Here's what I would do:
GuestTableViewController have a list of Person objects, Person object have a BOOL for selected or not.
GuestInfoViewController, reads the BOOL value to show the switch, if the value is changed it fires the delegate and updated the list in GuestTableViewController.
This way, everything is updated and you have all information correct. If you need help doing the delegate, you can find a million examples on Stackoverflow. Or ask and I'll elaborate.
** edit **
When dealing with a simple Person object, you don't even need a delegate, its simplier. Check the project in attach: http://www.brunotereso.net/temp/DelegateProject.zip (Please note this is just a piece of code I've put up to show you how to do it. If you implement something like this, have a look on cellForRowAtIndexPath and use reusable cells)
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;
}
}