Change the displayed unit instantly after user changes it using UISegmentedControl - objective-c

I have a UISegmentedControl that handles the setting of the temperature unit (ºC/ºF).
It works correctly but if the user changes the setting, the displayed unit won't change (refresh itself) unless the user navigates to another View Controller and then back to the one in question.
I'm using
- (void)viewWillAppear:(BOOL)animated
{
//Gets user setting choice for Fahrenheit or Celsius
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
temperatureSetting = [[preferences valueForKey:#"temperature setting"]intValue];
//For getting the current value of temperature from the JSON data
NSInteger temp = [[conditions objectForKey:#"temperature"]intValue];
//For checking the user's setting to display either Fahrenheit or Celsius
if (temperatureSetting == 0) {
temp = (temp * 1.8) + 32;
temperatureLabel.text = [NSString stringWithFormat:#"%i°F", temp];
} else {
temperatureLabel.text = [NSString stringWithFormat: #"%iºC", temp];
}
}
- (IBAction)temperatureSelection:(UISegmentedControl *)sender {
//Used to save settings
NSUserDefaults *temperaturePreference = [NSUserDefaults standardUserDefaults];
//To check which segment is selected and save the value but also remember it
if ([sender selectedSegmentIndex] == 0) {
[temperaturePreference setInteger:0 forKey:#"temperature setting"];
[selectedSegment setInteger:0 forKey:#"segment setting"];
} else if ([sender selectedSegmentIndex] == 1) {
[temperaturePreference setInteger:1 forKey:#"temperature setting"];
[selectedSegment setInteger:1 forKey:#"segment setting"];
}
//To make sure the setting is saved
[temperaturePreference synchronize];
[selectedSegment synchronize];
}
How can I make it change the displayed unit instantly after the user changes it?
Thank You!

Move the code inside viewWillAppear: to a separate method. Call that method when the user changes the settings.

Try to add that line of code before the end of - (IBAction)temperatureSelection:(UISegmentedControl *)sender method.
- (IBAction)temperatureSelection:(UISegmentedControl *)sender{
//..etc
temperatureSetting = [[temperaturePreferences valueForKey:#"temperature setting"]intValue];
if (temperatureSetting == 0) {
temp = (temp * 1.8) + 32;
temperatureLabel.text = [NSString stringWithFormat:#"%i°F", temp];
} else {
temperatureLabel.text = [NSString stringWithFormat: #"%iºC", temp];
}
[self.view setNeedsDisplayInRect:temperatureLabel.frame];//probably is not needed it forces the view to redraw itself as it mark as dirty
}

Related

Enable button only after text fields are entered

Apple started rejecting my app (after yrs of approvals) - I have 2 text fields for a few char of last, first name, then press Go. They claim - I can't reproduce that the app crashes if you just press Go - when I run it it tries to send the request but kicks it back with an error 'No name - please reenter'. Whatever. To appease Apple I edited my text field entry method to now (see below) - but still not working. Please advise.
// Text Field methods
-(void)textFieldDidBeginEditing:(UITextField *)textField {
UIFont* boldFont = [UIFont fontWithName:#"Helvetica-Bold" size: 24];
if (textField == _lastName) {
[_lastName becomeFirstResponder];
[_lastName setFont:boldFont];
_lastName.autocorrectionType = UITextAutocorrectionTypeNo;;
_lastName.autocapitalizationType = UITextAutocapitalizationTypeNone;
_lastName.text = #"";
NSLog(#"user editing last...");
// Enable button once fields have values
if ([_lastName.text isEqual: #""] && [_firstName.text isEqual: #""])
{
_fwdButton.enabled = YES;
}
}
else {
[_firstName becomeFirstResponder];
[_firstName setFont:boldFont];
_firstName.autocorrectionType = UITextAutocorrectionTypeNo;;
_firstName.autocapitalizationType = UITextAutocapitalizationTypeNone;
_firstName.text = #"";
NSLog(#"user editing first");
// Enable button once fields have values
if ([_lastName.text isEqual: #""] && [_firstName.text isEqual: #""])
{
_fwdButton.enabled = YES;
}
}
}
I was able to add code similar to[https://stackoverflow.com/questions/2859821/disable-button-until-text-fields-have-been-entered][1]
to deal with the situation.

Report achievement progress by increasing it instead of replacing it

I have trouble reporting achievements. I would like to do the following:
When I submit an achivment progress like 1%, I would like to increase the actuall progress not replaccing it.
So if I submit 1% and the user allready have like 4% its have to be 5% not 1%. Is there any way to do this?
Here my actual reporting code:
+(void)reportachivementwithidenfitier:(NSString *)identifier percentcompleted:(float)percent{
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
if ([defaults boolForKey:#"localplayeravailable"]) {
GKAchievement *achievement = [[GKAchievement alloc] initWithIdentifier: identifier];
if (achievement)
{
achievement.percentComplete = percent;
achievement.showsCompletionBanner=YES;
NSArray *achivments=[[NSArray alloc]initWithObjects:achievement,nil];
[GKAchievement reportAchievements:achivments withCompletionHandler:^(NSError *error){
if (error!=nil) {
NSLog(#"Achievement Submission failed with error:%#",[error description]);
}
else
{
NSLog(#"Achievement Succesfully reported");
}
}];
}
}
on this line:
achievement.percentComplete = percent;
you are setting it to a new value. Simply add the value to it, like so:
achievement.percentComplete += percent;

Updating UILabel and clearing it?

I have a UILabel that I start at "0" and then as my game progresses I call the below code to add "1" to the score each time a button is pressed. This all works fine.
playerOneScore.text = [NSString stringWithFormat:#"%d",[playerOneScore.text intValue]+1];
My problem is that when the game ends and the user presses the "Replay" button. This replay button sets the label back to "0" by calling this.
playerOneScore.text = #"0";
But then when the game progresses my label jumps from "0" to where it had initially left off + 1. What am I doing wrong here? Not making sense.
Any help would be very grateful! Thank you!
More code requested (simplified):
- (void)viewDidLoad
{
playerOneScore.text = #"0";
}
-(IBAction)touchDown {
if (playerOneTurn == YES) {
if (button1.touchInside == YES) {
playerOneScore.text = [NSString stringWithFormat:#"%d",[playerOneScore.text intValue]+1];
}
}
}
-(void) replayGame {
playerOneScore.text = #"0";
}
Not sure what's going on, but I would suggest using a separate NSInteger property to track the score. Then override the property setter to update the label text.
Add the property to your interface or a private category:
#property (nonatomic, assign) NSInteger score;
Then override the setter:
- (void)setScore:(NSInteger)value {
_score = value;
playerOneScore.text = [NSString stringWithFormat:#"%d", value];
}
Then in your action, update the score and label using the new property:
-(IBAction)touchDown {
if (playerOneTurn == YES) {
if (button1.touchInside == YES) {
self.score += 1;
}
}
}
Note that I haven't compiled or tested this code, but it should be close.
EDIT: fixed typo in setter

Obj-C - NSString that saves all input using currentTitle and UILabel.text methods

NSString* digit = [sender currentTitle];
if (self.userIsInTheMiddleOfEnteringANumber){
NSString* currentDisplayText = [[self display]text];
NSString* newDisplayText = [currentDisplayText stringByAppendingString:digit];
self.display.text = newDisplayText;
I´ll try and explain my problem as good as I can. This line of code here takes the digit from a selection of buttons, saves it no the string "digit". "currentDisplayText"takes the digit displayed in a label. Then these two strings are appended and sent to the "display" (label)
But there is also an enter button. Which clears the display (so user can enter new number ) this is a calculator btw!
- (IBAction)enterPressed{
[self.brain pushOperand:[self.display.text doubleValue]];
self.userIsInTheMiddleOfEnteringANumber = NO;
What I want is to display a "history" label that displays all the numbers entered - I have not quite understood how I get the string I save the "history" too, to not reset like the display does. This might be bad exlained by me, but any hints are appreciated. I am still learning objective-c...
If I understood you correctly, you want to save the number after pressing the enter button. For this you need to add an attribute of type NSMutableArray to your class. Then in the method do:
- (IBAction)enterPressed {
[myHistoryArrayAttrib addObject: self.display.text];
[self.brain pushOperand:[self.display.text doubleValue]];
self.userIsInTheMiddleOfEnteringANumber = NO;
//after this you can clear your display
self.display.text = nil;
}
That's it.
I did not understander you very well , but one thing I am sure , if you want save your data (not very large) , you should use NSUserDeafult . use - (void)setObject:(id)anObject forKey:(id)aKey;to save the data.
You want to svae the history , if you want to save the lastest history , you could use - (NSString *)stringForKey:(NSString *)defaultName; to get the string which you save. and if you want to save the whole history , you could use - (NSArray *)arrayForKey:(NSString *)defaultName; to get the array which you save.
give an eg. how to save a string
if([[NSUserDefaults standardUserDefaults] stringForKey:theKey] == nil)
{
NSString *defaultValue = [NSString stringWithString:theStringYouWantedSave];
NSDictionary *saveDict = [NSDictionary dictionaryWithObject:defaultValue forKey:theKey];
[[NSUserDefaults standardUserDefaults] registerDefaults:saveDict];
}
else
{
[[NSUserDefaults standardUserDefaults] setObject:theStringYouWantedSave forKey:theKey];
}
and get like this
if([[NSUserDefaults standardUserDefaults] stringForKey:theKey]!=nil)
{
yourHistoryString = [[NSUserDefaults standardUserDefaults] stringForKey:theKey];
}

Set NSPopUpButton at first launch

I have a NSPopUpButton but at first time launch this does not set correctly the first value. I have set awakeFromNib but the NSPopUpMenu is empty. Only the second time and the next it works correctly.
Thanks in advance.
-(IBAction)chancepesoalert:(id)sender{
int selection = [(NSPopUpButton *)sender indexOfSelectedItem];
NSNumber *valore = [NSNumber numberWithUnsignedLongLong:(30*1000*1000)];
if (selection == 0) {
valore = [NSNumber numberWithUnsignedLongLong:(30*1000*1000)];
NSLog(#"Selezionato 0");
}
if (selection == 1){
valore = [NSNumber numberWithUnsignedLongLong:(50*1000*1000)];
NSLog(#"Selezionato 1");
}
if (selection == 2){
valore = [NSNumber numberWithUnsignedLongLong:(75*1000*1000)];
NSLog(#"Selezionato 2");
}
if (selection == 3){
valore = [NSNumber numberWithUnsignedLongLong:(100*1000*1000)];
NSLog(#"Selezionato 3");
}
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:valore forKey:#"SetPesoAlert"];
[userDefaults synchronize];
}
-(void)awakeFromNib {
unsigned long long value = [[[NSUserDefaults standardUserDefaults] objectForKey:#"SetPesoAlert"] unsignedLongValue];
int index;
if (value == (30*1000*1000)) {
index =0;
}
if(value == (50*1000*1000)) {
index =1;
}
if(value == (75*1000*1000)) {
index =2;
}
if(value == (100*1000*1000)) {
index =3;
}
[pesoalert selectItemAtIndex:index];
}
I sounds like you need to use registerDefaults (you might not need to do this however, since the operating system will pick default values and 0 for an index is what it will pick I think). This allows you to set up default values for the first time an app is run, but if the user changes a default, that new default will be used the next time the app is run (but you need to read those defaults at start up -- I don't see any defaults reading in the code you posted).
There is however, an even easier way to do this using bindings. When I do popups, I use an array to supply the values to the popup menu. In IB, I delete the menu items that you get by default, and then bind the popup's content binding to, for instance, App Delegate.data (data is the name of my array). Then I bind the Selected Index to the Shared User Defaults Controller with a Model Key Path of whatever (it doesn't matter what you call it, this is a name that the controller uses, it's not a property in your code). When you start the app for the first time it defaults to index=0, so you will get whatever is the first item on your list, and any changes the user makes will be remembered on the next startup.