NSUserDefaults Settings Page Not Saving - ios

I would like to create a settings page, where it sets/gets the slider value (text Size) from NSUserDefaults, but my app is having none of it. I dont get any errors, it just doesn't want to save. I've commented the code, to help you understand better what I want to do, but it's quite simple. I have a 7-stage slider that has the font sizes, and you can simply slide it to determine what size of font you want - that is the value I want saved throughout the app. But whenever I press back on the navigation bar and open the settings page again, the default size is always 22.
.h
#interface SettingsViewController : UIViewController
#property (strong, nonatomic) IBOutlet UISlider *sizeSlider;
#property (strong, nonatomic) IBOutlet UILabel *sampleText;
#end
.m
#interface SettingsViewController () {
NSArray *numbers;
NSMutableAttributedString *sampleTextString;
int fontSize;
NSUserDefaults *defaults;
}
#end
#implementation SettingsViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = #"Settings";
numbers = #[#(10), #(12), #(14), #(16), #(18), #(20), #(22)]; // Text Sizes, these number values represent each slider position
NSInteger numberOfSteps = ((float)[numbers count]-1); // Slider values go from 0 to the number of values in your numbers array
self.sizeSlider.maximumValue = numberOfSteps; // As the slider moves it will continously call the -valueChanged:
self.sizeSlider.minimumValue = 0;
defaults = [NSUserDefaults standardUserDefaults]; //Setting the font to be the current font saved in the system
long textsize = [defaults integerForKey:#"fontSize"];
NSLog(#"textsize: %ld", textsize);
self.sizeSlider.value = textsize; // Set the Slider to whatever font you had set it previously
self.sizeSlider.continuous = YES; // NO makes it call only once you let go
[self.sizeSlider addTarget:self action:#selector(valueChanged:) forControlEvents:UIControlEventValueChanged];
sampleTextString = [[NSMutableAttributedString alloc] initWithString:#"The Quick Brown Fox Jumps Over The Lazy Dog!"];
self.sampleText.attributedText = sampleTextString;
[sampleTextString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:textsize] range:NSMakeRange(0, sampleTextString.length)];
}
-(void)valueChanged:(UISlider *)sender{
NSUInteger index = (NSUInteger)(self.sizeSlider.value + 0.5); // round the slider position to the nearest index of the numbers array
[self.sizeSlider setValue:index animated:NO];
NSNumber *number = numbers[index]; // <-- This numeric value you want
[sampleTextString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:[number floatValue]] range:NSMakeRange(0, sampleTextString.length)];
[defaults setInteger:[number integerValue] forKey:#"fontSize"]; // Saving fontSize to NSUserDefaults
[defaults synchronize];
self.sampleText.attributedText = sampleTextString;
}
#end

Answer comes from rmaddy - Thanks!
I needed to look at the index, rather than the actual value of the array.
NSInteger indexText = [numbers indexOfObject:[NSNumber numberWithInteger:textsize]];
So I put that in, and that returned the index of the slider position I wanted.

Related

How to save a rating control value?

I am playing around with DYRateView....a control at the end of a long list of controls I've tried out. It can be found here: https://github.com/dyang/DYRateView
The problem with all the controls I've tried is that I can't seem to save the rating once it's been changed. I'm using NSUserDefaults and have tried placing it in various places including where the value changes, where the view is set up, in viewDidLoad, in viewWillAppear, within the source code itself. Saving this value just has me flummoxed. I would appreciate any help. Just to get a sense of how this should work, I've just been working in the sample code that came with DYRateView. Here is the relevant code:
THE .M FILE
#import "DemoViewController.h"
#interface DemoViewController ()
- (void)setUpEditableRateView;
#end
#implementation DemoViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSUserDefaults standardUserDefaults] integerForKey:#"rating"];
[self setUpEditableRateView];
}
- (void)setUpEditableRateView {
DYRateView *rateView = [[DYRateView alloc] initWithFrame:CGRectMake(0, 40, self.view.bounds.size.width, 20) fullStar:[UIImage imageNamed:#"StarFullLarge.png"] emptyStar:[UIImage imageNamed:#"StarEmptyLarge.png"]];
rateView.padding = 20;
rateView.alignment = RateViewAlignmentCenter;
rateView.editable = YES;
rateView.delegate = self;
[self.view addSubview:rateView];
[rateView release];
}
- (void)rateView:(DYRateView *)rateView changedToNewRate:(NSNumber *)rate {
self.rateLabel.text = [NSString stringWithFormat:#"Rate: %d", rate.intValue];
[[NSUserDefaults standardUserDefaults] setInteger:rate forKey:#"rating"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
#end
Thanks to anyone who takes the time!
You are trying to save an NSNumber as an NSInteger. You should do [[NSUserDefaults standardUserDefaults] setInteger:[rate integerValue] forKey:#"rating"]; or use - setObject:forKey: because NSNumber is an object, not a scalar.
You are getting rating valuea at: [[NSUserDefaults standardUserDefaults] integerForKey:#"rating"]; but what are you doing with this value?
I think that you need to get this value and set to DYRateView. So:
Create a property of DYRateView: #property DYRateView * rateView
Set it on setUpEditableRateView: self.rateView = [[DYRateView alloc] initWithFrame:CGRectMake(0, 40, self.view.bounds.size.width, 20) fullStar:[UIImage imageNamed:#"StarFullLarge.png"] emptyStar:[UIImage imageNamed:#"StarEmptyLarge.png"]];
Update self.rateView (add it to end of setUpEditableRateView): rateView.rate = [[NSUserDefaults standardUserDefaults] integerForKey:#"rating"]

Array value not displaying in iOS simulator

I am making a simple calculator application that displays the equation that the user has inputed and also the output of the equation. At the top of my header file I created three integers and an array...
#import <UIKit/UIKit.h>
int Method;
int SelectNumber;
float RunningTotal;
NSMutableArray *Equation;
#interface SecondCalculatorViewController : UIViewController{
IBOutlet UILabel *EquationLabel;
IBOutlet UILabel *ResultLabel;
}
- (IBAction)OneButton:(id)sender;
- (IBAction)TwoButton:(id)sender;
- (IBAction)ThreeButton:(id)sender;
- (IBAction)FourButton:(id)sender;
- (IBAction)FiveButton:(id)sender;
- (IBAction)SixButton:(id)sender;
- (IBAction)SevenButton:(id)sender;
- (IBAction)EightButton:(id)sender;
- (IBAction)NineButton:(id)sender;
- (IBAction)ZeroButton:(id)sender;
- (IBAction)Plusbutton:(id)sender;
- (IBAction)MinusButton:(id)sender;
- (IBAction)MultiplyButton:(id)sender;
- (IBAction)DivideButton:(id)sender;
- (IBAction)CalculateButton:(id)sender;
- (IBAction)ClearButton:(id)sender;
#end
In my implementation, I prepare each input to be displayed in a label and then also I try to save SelectNumber into the first index in the array I created. I then try to display it in the label. Here is an example of one of the buttons...
- (IBAction)OneButton:(id)sender {
//[Equation addObject:0];
SelectNumber = SelectNumber * 10;
SelectNumber = SelectNumber + 1;
//EquationLabel.text = [NSString stringWithFormat:#"%i",SelectNumber];
[Equation replaceObjectAtIndex:0 withObject:[NSString stringWithFormat:#"%i",SelectNumber]];
EquationLabel.text = [Equation objectAtIndex:0];
}
When I run this in the simulator and push any number, it does not display the first value in the array "Equation".
How can I fix this?
It seems that Equation is not initialized. You need to initialize it:
Equation = [NSMutableArray new];
// or Equation = [[NSMutableArray alloc] init];
viewDidLoad method could be a good place for this code in your case.

My UILabel is not displaying when my if statement is false

I have a story board that has a UITextField, UIButton, UIImage, and UILabel to display the images in an array. If you type the correct name for the image file into a text field. So, the problem is that once the text field input does not match, it should update the UILabel to display "Result not found", but it doesn't.
#import "ViewController.h"
#interface ViewController ()
{
myClass *myNewClass;
NSMutableArray *picArray;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
picArray = [#[#"Button_Red",#"Button_Green"]mutableCopy];
}
- (IBAction)displayImageAction:(id)sender
{
NSString *titleSearched = self.textSearchField.text;
NSString *titleNotHere = self.notFoundLabel.text;
//Declare a bool variable here and set
BOOL variable1;
for (int i = 0; i < picArray.count; i++)
{
NSString *currentPic = picArray[i];
if ([titleSearched isEqualToString:currentPic])
{
variable1 = YES;
}
}
if (variable1 == YES) {
//this works fine displays the image
self.outputImage.image = [UIImage imageNamed: titleSearched];
[self.textSearchField resignFirstResponder];
} else {
//problem is here its not showing when input for the array is not equal it should display a message label "Result Not Found" but it remains blank on the IOS simulator
titleNotHere = [NSString stringWithFormat:#"Result Not found"];
[self.textSearchField resignFirstResponder];
}
}
//Get rid of the texfield when done typing
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// Retract keyboard if up
[self.textSearchField resignFirstResponder];
}
Your problem is that
titleNotHere = [NSString stringWithFormat:#"Result Not found"];
simply sets the method variable titleNotHere.
What you want is
self.notFoundLabel.text=#"Result Not found";
You will also want
self.notFoundLabel.text=#"";
when the result is found.
I think you will have to SET the value to the variable
self.notFoundLabel.text = [NSString stringWithFormat:#"Result Not found"]
or
self.notFoundLabel setText:[NSString stringWithFormat:#"Result Not found"]
UILabel.text = #"whatever..." is actually converted into [UILable setText:#"whatever..."].
NSString *labelText = UILabel.text has to be thought as NSString *labelText = [UILabel text];
This:
NSString *titleNotHere = self.notFoundLabel.text;
stores the text from the label into a variable, but updating that variable again will not change the label text - it only changes what that variable points to.
You need to explicitly update the label text:
self.notFoundLabel.text = #"Result Not found";
note also that this uses a string literal - you don't need to use a format string as you aren't adding any parameters to it.
Also, when checking booleans, don't use if (variable1 == YES) {, just use if (variable1) { (it's safer).

How to set the titleLabel.text of a UIButton?

I would like to know how to do that properly because I am getting a Bad Access error.
In my app I have 81 UIButtons with an IBAction attached to all of them by Interface Builder, this IBAction should set the text of the button the user tapped on. I am trying to do that this way:
- (IBAction)changeTitle:(UIButton *)button {
button.titleLabel.text = [NSString stringWithFormat:#"%#", myString];
}
-(IBAction)setMyString:(id)sender{
myString = [NSString stringWithFormat:#"text"];
}
However this comes into a Bad Access Error, how could I solve that?
Million Thanks!
error message: EXC_BAD_ACCESS (code=1, address=0x0)
(lldb)
You should not try to set the label text directly, but use UIButton setTitle:forState::
- (IBAction)changeTitle:(UIButton *)sender {
[button setTitle:myString forState:UIControlStateNormal];
}
The label property can be used to configure things like the font and other properties of the label, but some of them (color, shadow color and text) have to be set using the UIButton methods.
You might have a memory management problem. You are not using a #property to set your instance variable. You are setting it manually so you have to manage the memory yourself.
-(IBAction)setMyString:(id)sender{
[myString release]; // release old instance
myString = [[NSString stringWithFormat:#"text"] retain];
}
or even better, create a #property for your variable if you haven't done so already and set your variable by using the setter. Like this:
#property (copy, nonatomic) NSString *string; // in your #interface
#synthesize string = myString; // in your #implementation
-(IBAction)setMyString:(id)sender{
self.string = [NSString stringWithFormat:#"text"]; // setter will release old value, and retain new value
}
- (IBAction)changeTitle:(UIButton *)button {
// you should not set the text of the titleLabel directly
[button setTitle:self.string forState:UIControlStateNormal];
}

multiple UIButtons for one action, read the current button and store it as a temp value

I'm a beginner working on an emotion annotation application. There are several buttons like "happy","angry" and etc... All the buttons will call a same action. And there is an UISlider. If you click on "happy" , then you adjust the slider to annotate how happy you are now. After that you click on button "angry", the current value of slider will be stored in an float variable relatived to the last button, like "happy". Then you adjust the same slider to annotate how "angry" you are. And the next button....
I don't have idea about how to store the slider value for the last button...
Are there any ideas?
Thank you very much!!
There are many ways to approach this. One of the most simple solutions is to tag your buttons, and then use a method to work out which button the action came from, set up a dictionary object with the slider value inside it, and then write it to a strong array accordingly.
MainViewController.h
int emotionNumber
#property (strong, nonatomic) NSMutableArray *array;
//Declare your slider and buttons
MainViewController.m
#implementation
#synthesise array;
- (void)viewDidLoad {
[happyButton setTag:0];
[angryButton setTag:1];
array = [[NSMutableArray alloc] initWithCapacity:X]; <---- number of emotions
}
- (IBAction)setValue:(id)sender {
// You will also want to keep track of emotionNumber (the int) here, and modify the
//code below to write it to the correct place in the array.
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
UIButton *button = (UIButton *)sender;
switch (button.tag) {
case 0:
[dictionary setValue:slider.value forKey:#"angry"];
[array addObject:dictionary];
break;
case 1:
[dictionary setValue:slider.value forKey:#"happy"];
[array addObject:dictionary];
break;
default:
break;
}
}

Resources