xcode - Label changes value when I change views - ios

I have searched around and cannot find anything, help would be appreciated. I am very new to objective-C and Xcode.
In my app the player starts with 100 coins, this is represented in a label. When the user clicks a button to spend 10 coins, a popup box appears and asks 'are you sure', the user can click ok, or cancel.
If the user clicks 'ok' they spend 10 coins. At the moment, in the simulator when i'm in the same view everything is fine, the 100 goes down to 90 etc...
But when I go to another view and then back again, the coin amount goes back up to 100. This is the same when the user exits the app.
Here is my code:
.h file
//Coin
IBOutlet UILabel * coinCount;
.m file
int coinAmount = 100;
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
NSLog(#"user pressed Cancel");
// Any action can be performed here
}
else
{
NSLog(#"user pressed OK");
coinAmount -= 10;
[coinCount setText:[NSString stringWithFormat:#"%d", coinAmount]];
NSString * string = [NSString stringWithFormat:#"%d", coinAmount];
//Save coin amount
NSString * saveCoinAmount = string;
NSUserDefaults * defaultsCoinAmount = [NSUserDefaults standardUserDefaults];
[defaultsCoinAmount setObject:saveCoinAmount forKey:#"saveCoinLabel"];
[defaultsCoinAmount synchronize];
}
}
That seems to save the new coin amount, so now when the user goes to another view and back i try and load the saved coin amount:
- (void)viewDidLoad
{
[super viewDidLoad];
//Coin Label
NSUserDefaults * defaultsLoadCoin = [NSUserDefaults standardUserDefaults];
NSString * loadCoinLabel = [defaultsLoadCoin objectForKey:#"saveCoinLabel"];
[coinCount setText:loadCoinLabel];
}
Any help would be greatly appreciated!

Your problem is that you are storing your coins in two places - an integer variable and the label. When you return to your view you restore the saved coin amount directly into the label, but when you perform the "purchase" you use the integer, which has been re-initialised to 100.
I also suggest you get out of the habit of using instance variables and use properties.
You should do something like this -
.m file
#interface MyClass () // Change this to suit your class name
#property NSInteger coinAmount;
#property (weak,nonatomic) IBOutlet UILabel *coinLabel;
#end
#implementation MyClass
- (void)viewDidLoad
{
[super viewDidLoad];
//Coin Label
NSUserDefaults * defaultsLoadCoin = [NSUserDefaults standardUserDefaults];
if ([defaultsLoadCoin objectForKey:#"coins] == nil) {
self.coinAmount=100;
[defaultsLoadCoin setInteger:self.coinAmount forKey:#"coins"];
}
else {
self.coinAmount = [defaultsLoadCoin integerForKey:#"coins"];
}
self.coinLabel.text=[NSString stringWithFormat:#"%ld",self.coinAmount];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
NSLog(#"user pressed Cancel");
// Any action can be performed here
}
else
{
NSLog(#"user pressed OK");
self.coinAmount -= 10;
self.coinLabel.text=[NSString stringWithFormat:#"%ld",self.coinAmount];
//Save coin amount
NSString * saveCoinAmount = string;
NSUserDefaults * defaultsCoinAmount = [NSUserDefaults standardUserDefaults];
[defaultsCoinAmount setInteger:self.coinAmount forKey:#"coins"];;
[defaultsCoinAmount synchronize];
}

Your coinAmount property is not persistent through app launches or initialisations of the view controller in which it is created. You should consider persisting this value in database (like CoreData) or in NSUserDefaults.
My advice: start with basics (links to docs):
CoreData
NSUserDefaults

Related

Detect which tab we are in using CAPSPageMenu in objective c

I am using CAPSPageMenu with 2 tabs. Now there is an button at right bar button. When ever i click that i have an view with one button called sayHello. Now when i click that button i needs to know which tab i was in. That bar button is for both tabs.But how can i check which tab was i am when i click on that sayHello.
code :
In my homevc i added that two tabs .
VC1, VC2..
And i tried in viewwillAppear added on bool in nsuserdefault and tried to fetch. But that bool is always coming as TRUE. Which ever tab i am - still the bool values i coming as true.Here is an code :
In vc1
-(void)viewWillAppear:(BOOL)animated {
userDefault = [NSUserDefaults standardUserDefaults];
[userDefault setBool:TRUE forKey:#"fromVC1"]; // Tried true, YES also
NSLog(#"from vc1");
}
In vc2
-(void)viewWillAppear:(BOOL)animated {
userDefault = [NSUserDefaults standardUserDefaults];
[userDefault FALSE forKey:#"fromVC1"]; // Tried false, No also
NSLog(#"from vc1");
}
And i am checking like :
BOOL Val;
userDefault = [NSUserDefaults standardUserDefaults];
Val = [userDefault objectForKey:#"fromVC1"];
if (Val) {
NSLog(#"from VC1");
}else {
NSLog(#"from VC2");
}
But always its coming as True. Any idea how to get that ?Which tab i was i before. when i press my button sayHello.
- (void)didTapGoToLeft {
NSInteger currentIndex = self.pageMenu.currentPageIndex;
if (currentIndex > 0) {
[_pageMenu moveToPage:currentIndex - 1];
}
}
//
- (void)didTapGoToRight {
NSInteger currentIndex = self.pageMenu.currentPageIndex;
if (currentIndex < self.pageMenu.controllerArray.count) {
[self.pageMenu moveToPage:currentIndex + 1];
}
}
if you conform with delegate of CAPSPageMenu, you get the tab with the following two delegate methods.
// Optional delegate
- (void)willMoveToPage:(UIViewController *)controller index:(NSInteger)index {}
- (void)didMoveToPage:(UIViewController *)controller index:(NSInteger)index {}
for e.g
Intially, you nee to tell the compiler that your class implements the protocol:
#interface ViewController : UIViewController<CAPSPageMenuDelegate>
#property (nonatomic) CAPSPageMenu *pagemenu;
thereafter you need to conform the delegate
_pageMenu.delegate = self;
and finally access the delegate as your need.
(void)didMoveToPage:(UIViewController *)controller index:(NSInteger)index {
NSLog(#"controller: %#", controller);
NSLog(#"tabbed Index : %d", index);
}
for step by step intro : https://github.com/PageMenu/PageMenu/blob/master/README.md
I quite agree with the #Anbu.Karthik. Karthik implementation
But I would like to answer that you always get TRUE value when userDefault appears
Because you do not provide a full method context to read the userDefault Value.
So I don't know if it's due to the call life cycle, but if you try to write userDefault methods to viewDidAppear:(BOOL)animated, I'm sure you'll get the expected values.
Schematic code:
- (void)viewDidAppear:(BOOL)animated {
BOOL value;
NSUserDefaults* userDefault = [NSUserDefaults standardUserDefaults];
value = [userDefault objectForKey:#"fromVC1"];
}
I hope I can help you

How to retrieve UISwitch state in each of my UITableView cells?

I have a UISwitch set as the accessoryView in each of my TableView cells.
If I press my Confirm button, I want to save the state of each UISwitch with NSUserDefaults. Then when I leave and go back to that View Controller, I should be able to load those saved states which will be different for each cell (either on or off, as shown in image).
I'm almost there but I guess I am not sure how to save/load with the right indexPath.row so it's not working correctly. Right now it is just saving/loading one BOOL value only, so if I save one cell with the switch ON, then all of them will be ON, and vice versa.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
BOOL menuSwitchState = [[NSUserDefaults standardUserDefaults] boolForKey:#"menuItemSwitch"];
NSLog(#"Menu Switch State is: %#", menuSwitchState ? #"Yes": #"No");
[self.switchView setOn:menuSwitchState animated:YES];
}
UISwitch code in my cellForRowAtIndexPath:
// Add a UISwitch to the accessory view.
self.switchView = [[UISwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = self.switchView;
self.switchView.tag = indexPath.row;
self.switchView.on = [[NSUserDefaults standardUserDefaults] boolForKey:#"menuItemSwitch"];
[self.switchView addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
Switch action method which sets a BOOL:
- (void) switchChanged:(id)sender {
UISwitch *switchControl = sender;
NSLog(#"The switch's tag number is %ld", (long)switchControl.tag);
// NSLog(#"The switch is %#", switchControl.on ? #"ON" : #"OFF" );
if ([sender isOn])
{
self.switchIsOn = YES;
NSLog(#"THE SWITCH IS ON");
}
else
{
self.switchIsOn = NO;
NSLog(#"THE SWITCH IS OFF");
}
}
Confirm button that should save the state of the switch:
#pragma mark - UIBUTTONS
- (IBAction)onConfirmMenuButtonPressed:(id)sender
{
[self performSegueWithIdentifier:#"segueMenuToGettingStarted" sender:self];
//TODO: Save state of Switch.
if (self.switchIsOn == YES)
{
[[NSUserDefaults standardUserDefaults] setBool:self.switchView.on forKey:#"menuItemSwitch"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
else
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[ud setBool:NO forKey:#"menuItemSwitch"];
}
}
You save that value just like any other value you use in a table view -- in an array that's your data source. Given what you show in your image, your data source should be an array of dictionaries with keys for the menu item, price, and switch state. In cellForRowAtIndexPath, you would set the state of the switch based on the value ( a BOOL) in your array.
in your code, you just set one NSUserDefault value for the all items(now, looks like three), I think you must separate each kind of item, it means you must have the count of NSUserDefault same as the count of UISwitch, In UIViewController, you can hold the NSUserDefault values in an Array, when you change the switch, you changed the cell data, when you leave the ViewController, save the Array's values. Enter the ViewController, update the Array.

Recording A Users Interaction With Interface

I have a lot of UIButtons in my app. I need to record which ones the user pushed, exactly the time elapsed between each button press, and then relay the information back to the user. Now, I've tried figuring out the logic to do this for quite some time. This is what I've tried first:
I start by firing an NSTimer. Every time the user presses a button, I store the time he pushed the button in arrayOne, and store the button he pushed in arrayTwo.
I have a "Playback" button. The goal of this playback button is to loop through both arrays, programatically pushing the buttons the user pressed at the elapsed time in which they pressed them.
I can probably achieve my goal this way, but this is just messy code and I don't like the design of it at all. What I'm looking for is an easier path. Is there an API that will record and playback the interaction?
I've found various links such as:
Audio Recording and Playback
That achieve similar to what I'm trying to do, but the sounds I'm loading into the app that play when each button is tapped are not recorded via microphone. They are included in the bundle.
What I did for the solution was make every button have a unique tag and call the same method "onAppButtonPressed" using tags to execute specific code for each button. Before anything though I created a fake button execution so I could mark when the app was opened. After executing button specific code when a UIButton was pressed, I stored information in an array with the button's tag and the button's fire date. When I call the startPlayback method, a for loop loops through all of the button data and schedules each button with the correct timing since the view loaded. I made a simple storyboard with three test buttons and a start playback button.
View Controller:
#import "PlaybackButtonEventViewController.h"
#import "ButtonPlaybackData.h"
#interface PlaybackButtonEventViewController ()
#end
#implementation PlaybackButtonEventViewController
{
NSMutableArray *playbackInformationArray;
BOOL playbackMode;
}
#define kInitialPlaybackData -1
#define kButtonOneId 1
#define kButtonTwoId 2
#define kButtonThreeId 3
#define kPlaybackButtonId 4
- (void) viewDidLoad
{
[super viewDidLoad];
self->playbackInformationArray = [NSMutableArray array];
self->playbackMode = false;
ButtonPlaybackData *initialPlaybackData = [[ButtonPlaybackData alloc] init];
initialPlaybackData.buttonTag = kInitialPlaybackData;
initialPlaybackData.buttonFireDate = (NSDate*) [NSDate date];
[self->playbackInformationArray addObject:initialPlaybackData];
}
- (void) startPlaybackMode
{
self->playbackMode = true;
for (int playbackIndex = 0; playbackIndex < self->playbackInformationArray.count; playbackIndex++)
{
ButtonPlaybackData *currentPlaybackData = [self->playbackInformationArray objectAtIndex:playbackIndex];
if (currentPlaybackData.buttonTag == kInitialPlaybackData)
continue;
ButtonPlaybackData *initialPlaybackData = [self->playbackInformationArray objectAtIndex:0];
long timeToWait = (currentPlaybackData.buttonFireDate.timeIntervalSince1970 - initialPlaybackData.buttonFireDate.timeIntervalSince1970);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timeToWait * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self onAppButtonPressed:[self.view viewWithTag:currentPlaybackData.buttonTag]];
if ((playbackIndex + 1) == self->playbackInformationArray.count)
{
self->playbackMode = false;
NSLog(#"Playback has ended!");
}
});
}
}
- (IBAction) onAppButtonPressed: (id) sender
{
if (![sender isKindOfClass:[UIButton class]])
return;
UIButton *button = (UIButton*) sender;
switch (button.tag)
{
case kButtonOneId:
NSLog(#"Button one pressed!");
break;
case kButtonTwoId:
NSLog(#"Button two pressed!");
break;
case kButtonThreeId:
NSLog(#"Button three pressed!");
break;
case kPlaybackButtonId:
[self startPlaybackMode];
break;
}
if (!playbackMode)
{
ButtonPlaybackData *buttonPlaybackData = [[ButtonPlaybackData alloc] init];
buttonPlaybackData.buttonTag = button.tag;
buttonPlaybackData.buttonFireDate = (NSDate*) [NSDate date];
[self->playbackInformationArray addObject:buttonPlaybackData];
}
}
#end
Now for the ButtonPlaybackData object, it has the following header file with an empty m file:
#import <Foundation/Foundation.h>
#interface ButtonPlaybackData : NSObject
#property(nonatomic) NSInteger buttonTag;
#property(nonatomic, retain) NSDate *buttonFireDate;
#end
Hope this helps!

Check Which Order Buttons Are Pressed Objective-C

I am developing an app that I need to check which order buttons are pressed in. I had 3 buttons and if they are pressed in the incorrect order I will have a UIAlertView. How can I check the order of presses?
Thanks
You could wire up an action to the buttons (like "Touch Up Inside"), and have it log which buttons are pressed, and maybe have a counter incrementing as well. Then when the counter gets to three, have it go through the list of button presses, and verify if they are the order you anticipate.
Below is an example of what I mean. For this example, you have to wire up all 3 buttons "Touch Up Inside" to that same IBAction. Of course you replace the NSLogs with your UIAlertView, but this shows the gist of what I said.
#interface comboSOTestViewController ()
#property (strong, nonatomic) NSMutableArray *buttonTitles;
#end
#implementation comboSOTestViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.buttonTitles = [[NSMutableArray alloc]init];
}
- (IBAction)comboButtonPress:(UIButton *)sender
{
[self.buttonTitles addObject:sender.titleLabel.text];
if (self.buttonTitles.count > 2)
{
BOOL bad = NO;
NSArray *correctOrder = #[#"Second", #"Third", #"First"];
for (int i=0; i < 3; i++)
{
if (![self.buttonTitles[i] isEqualToString:correctOrder[i]])
{
bad = YES;
}
}
if (bad == YES)
{
NSLog(#"WRONG ORDER");
}
else
{
NSLog(#"CORRECT ORDER");
}
}
}

don't show again ViewController

In my app, I created a first ViewController (in storyboard) called welcome, with all the instructions. At the end of the page, I wanted to insert a box that could be selected showing "don't show again". By clicking on this box, and going to the next page, the first viewController will vanish. When I reopen the app, the controller won't be shown again. The only way to show it is by going on settings and selecting the switch "repristinate original settings" or something like that. Please, can anyone help me? Thanks!
I found an example but is not what I want:
- (IBAction)leggi{
NSString *stringaTesto = campo.text;
testo.text = [[NSString alloc] initWithFormat:#"%#", stringaTesto];
NSString *testoInserito = testo.text;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:testoInserito forKey:#"ciao"];
[defaults synchronize];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *testoSalvato = [[NSUserDefaults standardUserDefaults] objectForKey:#"ciao"];
if (testoSalvato == nil) {
testo.text = #"Non hai ancora inserito il tuo nome";
} else {
testo.text = [[NSString alloc] initWithFormat:#"Ciao %#", testoSalvato];
}
}
The IB Outlet is linked to a button
store the don't show again as a BOOL in NSUserDefaults.. and check it before showing the view..
if it is TRUE..dont show.other wise show it.
edit
Lets say you have your app delegate and currently show your don't show view again (Lets say A) from it ..after which you show another view(Lets say B)
then in your app delegate you have to get a BOOL
like this
BOOL _Dont_Show_Again = [NSUSerDefaults standardDefaults] boolForkey : #"Don't Show"];
if(_Dont_Show_Again)
{
load B Code here...
}
else
{
load A Code here;
}
first time _Dont_Show_Again will be 0 since it does not exist in default..but if user select don't show you should save it in the default and this code will then work fine for you

Resources