Simple slider app, quick question - objective-c

Everything looks right, and yet something is missing. Could you please take a look?
.m
#synthesize textLabel;
#synthesize slider;
- (IBAction)setLabel:(id)sender {
int res = [slider value];
NSLog(#"something changed %d", res);
[textLabel setText:[NSString stringWithFormat:#"%d",[slider value]]];
}
.h
#interface SlidaAppDelegate : NSObject {
UILabel *textLabel;
UISlider *slider;
NSString *text;
}
- (IBAction)setLabel:(id)sender;
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UILabel *textLabel;
#property (nonatomic, retain) IBOutlet UISlider *slider;
Whenever slider moves, i see value update correctly, however simulator shows strange numbers
Simulator shows
Xib setup is as follows:
Please advise
*UPDATE <---------------------------------------- *
Problem went away when i changed
[textLabel setText:[NSString stringWithFormat:#"%d",[slider value]]];
to
[textLabel setText:[NSString stringWithFormat:#"%d",res]];
I don't fully understand why that it though, considering that
int res = [slider value];
If possible, please explain

My bet is that value returns a float which is in between 0 and 1. So when you assign it to an int, it gets rounded down to 0.
Make res a float.
EDIT
%d wants an int, you were giving it a float with [slider value]. So it must have interpreted that value in a strange way. See DOC

Related

Array of UIButtons, can't change button image

I have an array of UIButton objects (I have 15 buttons so I wanted to store them in an array for easy processing). I want to be able to iterate through the array and change the background image/image that the button uses. This is how I currently have it set up:
#property (nonatomic, weak) UIImage *greenLight;
#property (nonatomic, weak) UIImage *yellowLight;
#property (nonatomic, weak) UIImage *redLight;
#property (weak, nonatomic) IBOutlet UIButton *task1Button;
#property (weak, nonatomic) IBOutlet UIButton *task2Button;
#property (weak, nonatomic) IBOutlet UIButton *task3Button;
#property (nonatomic, copy) NSMutableArray *buttonArray;
- (instancetype)init
{
self = [super init];
if(self){
[self.buttonArray addObject:self.task1Button];
[self.buttonArray addObject:self.task2Button];
[self.buttonArray addObject:self.task3Button];
self.greenLight = [UIImage imageNamed:#"greenlight.ICO"];
self.yellowLight = [UIImage imageNamed:#"yellowlight.ICO"];
self.redLight = [UIImage imageNamed:#"redlight.ICO"];
NSLog(#"init complete...");
}
return self;
}
Then I have the following in viewWillAppear
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.task1Button setImage:self.redLight forState:UIControlStateNormal];
[(UIButton *)self.buttonArray[1] setImage:self.greenLight forState:UIControlStateNormal];
}
The second line in viewWillAppear works and changes the button's image. The third line, however, does not. The debugger shows the code reaching that line and not throwing any errors, so I don't know why setting the button image when the button is in an array would not work.
Any ideas?
Try replacing last line in your answer with this :
[(UIButton *)[self.buttonArray objectAtIndex:1] setImage:self.greenLight forState:UIControlStateNormal];
But i'm doing this without compiler so i'm not really sure about where to place the first bracket [
Tell me if it works, i'm not totally sure about it.

pass slider value to subview

I have a UISlider placed in my main view and I have added a subview UIView (via interface builder) that I have associated with its own class SecondView. I need to pass the value of the slider to my sub view to move a point in the sub view when the slider changes.
I have made changes to the original code and the the below paragraph no longer is accurate. I used used the suggested changes offered by #MatthiasBauch.
I thought it would be simple a matter of sharing an iVar between the two. I created an iVar myPoint using #property (if this is still considered an iVar) in my ViewController interface, set myPoint = sliderValue.value in my ViewController implementation in the IBAction for when the slider value changes. Then in my SecondView implementation I #import "ViewController.h" then call my call my iVar in my SecondView implementation but the way I have done it it only returns nil or 0 instead of the slider value.
I don't want to use global variables.
I have looked at other post that seem to be asking a similar question but I'm still missing the concept, I guess. My code is below.
ViewController.h
#import <UIKit/UIKit.h>
#import "SecondView.h"
#interface ViewController : UIViewController
{
SecondView *secondView; // Do I need this with secondView declared as a #property below?
}
#property (nonatomic, retain) SecondView *secondView;
- (IBAction)sliderChanged:(id)sender;
#property (weak, nonatomic) IBOutlet UISlider *sliderValue;
#property (weak, nonatomic) IBOutlet UILabel *myLabel;
#property (weak, nonatomic) IBOutlet UIView *myView;
#end
ViewController.m
#import "ViewController.h"
#import "SecondView.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize sliderValue, myLabel, myView, secondView;
- (void)viewDidLoad
{
[super viewDidLoad];
secondView.thePoint = 50;
NSLog(#"%f", secondView.thePoint); // This is retuning a zero
}
- (IBAction)sliderChanged:(id)sender
{
secondView.thePoint = sliderValue.value;
myLabel.text = [NSString stringWithFormat:#"%.2f", sliderValue.value];
[secondView setNeedsDisplay];
}
#end
SecondView.h
#import <UIKit/UIKit.h>
#interface SecondView : UIView
#property (assign, nonatomic) CGFloat thePoint;
#end
SecondView.m
#import "SecondView.h"
#implementation SecondView
#synthesize thePoint;
- (void)drawRect:(CGRect)rect
{
float aPoint = thePoint;
NSLog(#"%f", aPoint); // this is retuning 0.000000
UIBezierPath *point = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(aPoint, 100, 4, 4)];
[point fill];
}
#end
Tell the view where to draw and don't ask the (newly allocated) viewController where to draw.
You are allocating a new viewController, this viewController of course does not know the value you set in the viewController where you actually changed the slider.
This won't work. Those two viewControllers are not the same instance. They share the same class, but that's it. Values from one viewController instance don't magically appear in a second instance.
Instead you should set a point property of the secondary view in your slider action.
Something like this:
Add a float #property to your view
#interface SecondView : UIView
#property (assign, nonatomic) CGFloat point;
#end
to draw use that point and not the initial value from a new ViewController instance.
- (void)drawRect:(CGRect)rect
{
float aPoint = self.point;
UIBezierPath *point = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(aPoint, 100, 4, 4)];
[point fill];
}
and set the point property of the secondary view in the slider action
- (IBAction)sliderChanged:(id)sender
{
secondView.point = sliderValue.value;
[secondView setNeedsDisplay]; // you might be able to omit that
myLabel.text = [NSString stringWithFormat:#"%.2f", myPoint];
}
Your ViewController has a property called #myView which points to the instance of SecondView created by the runtime.
So, your ViewController's implementation could call the drawRect: method on myView and pass in the relevant coordinates.
Here's some pseudo code for your ViewController.
- (IBAction)sliderChanged:(id)sender
{
myPoint = sliderValue.value;
myLabel.text = [NSString stringWithFormat:#"%.2f", myPoint];
[myView drawRect:CGRectMake(myPoint, 100, 4, 4)];
}
Note however that in your ViewController, myView is just a UIView, not a SecondView. You have a few choices on how to resolve this. The cleanest way is probably to remove the #import ViewController.h from SecondView and instead do the opposite. That is, have ViewController do an #import SecondView.h, then promote myView to a SecondView.
If that doesn't work for some reason (for example, if XCode demands that it remain strictly a UIView), you can still upcast the myView property at runtime like this:
[(*SecondView)myView drawRect:CGRectMake(myPoint, 100, 4, 4)];
Alternatively, you could point your slider's action at myView like the answer to this question does for a button: subclass UIView actions in viewcontroller
As usual in programming, there are several possible solutions. It's up to you to pick the best one for you. Good luck!

#protocol with integers

I am trying to make a protocol for a detail view for a tableView. The detail view has a question and then an answer. If I get the answer correct, it will set an integer to increase by 1 in a protocol method.
I am new to protocols and I don't understand what I am doing wrong.
Code
DetailViewController.h
Where the protocol is made
#import "Question.h"
#protocol DetailQuestionViewControllerDelegate <NSObject>
-(void)questionsCorrectHasChangedTo:(int)questionNumberChanged;
#end
#interface DetailQuestionViewController : UIViewController
#property (nonatomic, strong) Question *selectedQuestion;
#property (strong, nonatomic) IBOutlet UILabel *questionLabel;
#property (strong, nonatomic) IBOutlet UITextField *answerField;
#property (strong, nonatomic) IBOutlet UILabel *correctLabel;
#property (nonatomic,strong) id <DetailQuestionViewControllerDelegate> delegate;
#property (assign, nonatomic) int questionsCorrect;
DetailViewController.m
#implementation DetailQuestionViewController
#synthesize questionLabel;
#synthesize answerField;
#synthesize correctLabel;
#synthesize selectedQuestion;
#synthesize questionsCorrect;
#synthesize delegate;
- (void)viewDidLoad
{
[super viewDidLoad];
// Sets the questionLabel to the question we put in the array
self.questionLabel.text = [selectedQuestion questionName];
// Sets the navigation title to the rowName we put in the array
self.navigationItem.title = [selectedQuestion questionRowName];
NSLog(#"The question's answer for the question you selected is %#", [selectedQuestion questionAnswer]);
}
- (IBAction)checkAnswer:(UITextField *)sender
{
if ([[selectedQuestion questionAnswer] caseInsensitiveCompare:answerField.text] == NSOrderedSame)
{
// Show the correct label
[correctLabel setHidden:NO];
correctLabel.text = #"Correct!";
correctLabel.textColor = [UIColor greenColor];
*questionsCorrect = 1;
NSLog(#"questionsCorrect int is %d", questionsCorrect);
[self.delegate questionsCorrectHasChangedTo:questionsCorrect];*
}
else
{
// Show the incorrect label
[correctLabel setHidden:NO];
correctLabel.text = #"Incorrect";
correctLabel.textColor = [UIColor redColor];
}
// Erase the text in the answerField
answerField.text = #"";
}
ScoreViewController.h
Now here is my ScoreView which will be acsessing the delegate
#import <UIKit/UIKit.h>
#import "DetailQuestionViewController.h"
#interface ScoreViewController : UIViewController *<DetailQuestionViewControllerDelegate>*
#property (strong, nonatomic) IBOutlet UILabel *scoreLabel;
- (IBAction)resetButtonClicked:(UIButton *)sender;
-(void)checkScore;
#end
ScoreViewController.m
#import "ScoreViewController.h"
#import "DetailQuestionViewController.h"
#interface ScoreViewController ()
#end
#implementation ScoreViewController
#synthesize scoreLabel;
- (void)viewDidLoad
{
[super viewDidLoad];
*DetailQuestionViewController *dqvc = [[DetailQuestionViewController alloc] init];
dqvc.delegate = self;*
}
-(void)viewWillAppear:(BOOL)animated
{
[self checkScore];
}
-(void)checkScore
{
}
- (IBAction)resetButtonClicked:(UIButton *)sender
{
}
#pragma mark - DetailQuestionViewControllerDelegate -
*-(void)questionsCorrectHasChangedTo:(int)questionNumberChanged*
{
//set the textlabel text value to the number of questions correct
NSLog(#"questionsNumberChanged is %i", questionNumberChanged);
scoreLabel.text = [NSString stringWithFormat:#"You answered %d questions correctly",questionNumberChanged];
}
#end
The label is never updating for some reason.
Sorry for making the question so long, tried to be very specific.
I'm guessing somewhat here as you talk about increasing a value in a protocol method, yet you don't have a single + or ++ anywhere... You also have quite a few *'s sprinkled in strange places in your sample code, it is unclear whether these are typos, intended as emphasis, or intended to be pointer indirection.
So you have a property questionsCorrect in your DetailQuestionViewController class so let's assume this is the class you expect to own the counter (we'll skip that this is a view and not a model class...). If this is the idea then lines:
*questionsCorrect = 1;
NSLog(#"questionsCorrect int is %d", questionsCorrect);
[self.delegate questionsCorrectHasChangedTo:questionsCorrect];*
should be:
self.questionsCorrect++; // increment the counter
NSLog(#"questionsCorrect int is %d", self.questionsCorrect);
[self.delegate questionsCorrectHasChangedTo:self.questionsCorrect];
(you can also declare the instance variable questionsCorrect yourself and drop the use of self. above - whichever you prefer)
Now just go through and remove the other cases of extra *'s if they are in your code as well as the sample above and you'll be a bit closer to your goal.
If alternatively you wish ScoreViewController to own the counter then you need to declare it there and provide a method to increment and display it.
HTH

UISlider's value is not shown by UILabel

In my app, I have a Settings view, where the user can use UISlider to set value from 50 to 1000. The selected value is then shown in a UILabel.
The problem is that the label does not display at all. The Action and the IBOutlets are connected in IB. The NSLog displays the value correctly on the console.
I can't figure out what is going on....help is needed :)
I have the following:
IBOutlet UILabel *sliderLabel;
IBOutlet UISlider *slider;
...
#property (nonatomic, retain) UILabel *sliderLabel;
#property (nonatomic, retain) UISlider *slider;
-(IBAction) sliderValueChanged:(id) sender;
and
#synthesize sliderlabel, slider;
- (IBAction) sliderValueChanged:(UISlider *) sender {
NSString *sliderValue = [NSString stringWithFormat:#"%d feet",(int)[sender value]];
NSLog(#"%#", sliderValue);
[[self sliderLabel] setText: sliderValue];
}
Thanks, and regards.

specifying textField using UITextField delegate

Hi i'm new to software for iphone/ipad apps.
I am using the textField delegate method:
"(BOOL)textFieldShouldReturn:(UITextField *)textField".
I have gotten to the point where when the user enter a name and presses 'enter' and a label displays what the user just wrote. This is just two lines of code like so:
labelChange.text = textField.text; //labelChange is my label in IB
return YES;
Since i have several textfields in IB, this code works for all of them. I'm not sure how to be specific with the code and have this label change for only ONE of my textFields.
My .h files looks like this.
#interface FirstViewController : UIViewController <UITextFieldDelegate> {
IBOutlet UILabel *labelChange;
IBOutlet UITextField *userName;
IBOutlet UITextField *homeValue;
IBOutlet UITextField *downPayment;
IBOutlet UITextField *textField;
}
#property (nonatomic,retain) UILabel *labelChange;
#property (nonatomic,retain) UITextField *userName;
#property (nonatomic,retain) UITextField *homeValue;
#property (nonatomic,retain) UITextField *downPayment;
#property (nonatomic,retain) UITextField *textField;
#end
I want my label to change only when user types in the text field labeled "userName".I'm not sure how to do this, am I missing something?In IB, I connected all my textfield delegates to 'Files Owner'. Any advice would be really helpful. thanks!
Assign each of your text fields a tag number i.e.
textField1.tag = 1
textField2.tag = 2
etc...
Then in your -(BOOL)textFieldShouldReturn:(UITextField *)textField you can do a:
switch (textField.tag) {
case 1:
labelChange1.text = textField.text;
break;
case 2:
labelChange2.text = textField.text;
break;
etc... etc...
}