How to keep view controllers running in the background? - objective-c

Ok so I have two view controllers in my app. On the first one there is a timer and on the second a stopwatch. How do i keep the timers going for the different views when i am switching between them?
At the moment when i change view the timer stops and everything resets.
First views .m file:
#import "ViewController.h"
#import <AudioToolbox/AudioToolbox.h>
#interface ViewController ()
//TIMER
//labels
#property (weak, nonatomic) IBOutlet UILabel *timeLabelHour;
#property (weak, nonatomic) IBOutlet UILabel *timeLabelMin;
#property (weak, nonatomic) IBOutlet UILabel *timeLabel;
//buttons
#property (weak, nonatomic) IBOutlet UIBarButtonItem *timerWindow;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *stopwatchWindow;
#property (weak, nonatomic) IBOutlet UIButton *stop;
#property (weak, nonatomic) IBOutlet UIButton *start;
#property (weak, nonatomic) IBOutlet UIButton *reset;
//steppers
#property (weak, nonatomic) IBOutlet UIStepper *stepper;
#property (weak, nonatomic) IBOutlet UIStepper *Minstepper;
#property (weak, nonatomic) IBOutlet UIStepper *Hourstepper;
#end
#implementation ViewController
-(void) timerRun{
if(pause == NO){
overall = overall - 1;
int hours = overall / 3600;
int minutes = overall - (hours * 3600);
int minCon = minutes / 60;
int seconds = minutes - (minCon * 60);
NSString *timerOutputHour = [NSString stringWithFormat:#"%d", hours];
NSString *timerOutputMin = [NSString stringWithFormat:#"%02d", minCon];
NSString *timerOutput = [NSString stringWithFormat:#"%02d", seconds];
self.timeLabelHour.text = timerOutputHour;
self.timeLabelMin.text = timerOutputMin;
self.timeLabel.text = timerOutput;
if(overall == 0){
[Countdown invalidate];
Countdown = nil;
UILocalNotification *timeFinNotification = [[UILocalNotification alloc] init];
timeFinNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow: 1];
timeFinNotification.alertBody = #"Your timer has finished";
timeFinNotification.timeZone = [NSTimeZone defaultTimeZone];
[[UIApplication sharedApplication] scheduleLocalNotification:timeFinNotification];
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
self.Hourstepper.enabled = YES;
self.Minstepper.enabled = YES;
self.stepper.enabled = YES;
timer = 0;
timerMin = 0;
self.start.enabled = YES;
self.stop.enabled = NO;
self.reset.enabled = NO;
}
}
}
-(void) setTimer{
overall = (timerMin * 60) + (timerHour * 60 * 60) + timer;
Countdown = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timerRun) userInfo:nil repeats:YES];
self.Hourstepper.enabled = NO;
self.Minstepper.enabled = NO;
self.stepper.enabled = NO;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.stepper.autorepeat = YES;
self.stepper.wraps = YES;
self.stepper.minimumValue = 0;
self.stepper.maximumValue = 59;
self.stepper.stepValue = 1;
self.Minstepper.autorepeat = YES;
self.Minstepper.wraps = YES;
self.Minstepper.minimumValue = 0;
self.Minstepper.maximumValue = 59;
self.Minstepper.stepValue = 1;
self.Hourstepper.autorepeat = YES;
self.Hourstepper.wraps = YES;
self.Hourstepper.minimumValue = 0;
self.Hourstepper.maximumValue = 23;
self.Hourstepper.stepValue = 1;
self.start.enabled = YES;
self.stop.enabled = NO;
self.reset.enabled = NO;
timer = self.stepper.value;
timerMin = self.Minstepper.value;
timerHour = self.Hourstepper.value;
}
- (IBAction)start:(id)sender{
if(pause == NO && (timer != 0 || timerMin != 0 || timerHour != 0)){
[self setTimer];
}
pause = NO;
if(timer != 0 || timerMin != 0 || timerHour != 0){
self.start.enabled = NO;
self.stop.enabled = YES;
self.reset.enabled = YES;
}
}
- (IBAction)stop:(id)sender{
pause = YES;
self.start.enabled = YES;
self.stop.enabled = NO;
self.reset.enabled = YES;
}
- (IBAction)reset:(id)sender{
[Countdown invalidate];
Countdown = nil;
self.Hourstepper.enabled = YES;
self.Minstepper.enabled = YES;
self.stepper.enabled = YES;
self.timeLabelHour.text = #"0";
self.timeLabelMin.text = #"00";
self.timeLabel.text = #"00";
self.stepper.value = 0;
self.Minstepper.value = 0;
self.Hourstepper.value = 0;
timer = 0;
timerMin = 0;
timerHour = 0;
pause = NO;
self.start.enabled = YES;
self.stop.enabled = NO;
self.reset.enabled = NO;
}
- (IBAction)stepperValueChanged:(UIStepper *)sender
{
timer = sender.value;
self.timeLabel.text = [NSString stringWithFormat:#"%02d",timer];
}
- (IBAction)stepperValueChangedMin:(UIStepper *)sender
{
timerMin = sender.value;
self.timeLabelMin.text = [NSString stringWithFormat:#"%02d",timerMin];
}
- (IBAction)stepperValueChangedHour:(UIStepper *)sender
{
timerHour = sender.value;
self.timeLabelHour.text = [NSString stringWithFormat:#"%d",timerHour];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark iAd Delegate Mathods
-(void)bannerViewDidLoadAd:(ADBannerView *)banner{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
[banner setAlpha:1];
[UIView commitAnimations];
}
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
[banner setAlpha:0];
[UIView commitAnimations];
}
#end
Second Views .m file:
#import "ViewControllerStopwatch.h"
#interface ViewControllerStopwatch ()
//STOPWATCH
//labels
#property (weak, nonatomic) IBOutlet UILabel *stopLabelHour;
#property (weak, nonatomic) IBOutlet UILabel *stopLabelMin;
#property (weak, nonatomic) IBOutlet UILabel *stopLabel;
#property (weak, nonatomic) IBOutlet UILabel *stopLabelMilli;
//buttons
#property (weak, nonatomic) IBOutlet UIBarButtonItem *timerWindow;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *stopwatchWindow;
#property (weak, nonatomic) IBOutlet UIButton *start;
#property (weak, nonatomic) IBOutlet UIButton *reset;
#property (weak, nonatomic) IBOutlet UIButton *stop;
#end
#implementation ViewControllerStopwatch
-(void) timerRun{
if(pause == NO){
overall = overall + 1;
hours = overall / 3600;
minutes = overall - (hours * 3600);
minCon = minutes / 60;
seconds = minutes - (minCon * 60);
NSString *timerOutputHour = [NSString stringWithFormat:#"%d", hours];
NSString *timerOutputMin = [NSString stringWithFormat:#"%02d", minCon];
NSString *timerOutput = [NSString stringWithFormat:#"%02d", seconds];
self.stopLabelHour.text = timerOutputHour;
self.stopLabelMin.text = timerOutputMin;
self.stopLabel.text = timerOutput;
}
}
-(void) timerRunMilli{
if(pause == NO){
overallMilli = overallMilli + 1;
milliseconds = overallMilli;
if(overallMilli >= 99){
overallMilli = 0;
}
NSString *timerOutputMilli = [NSString stringWithFormat:#"%02d", milliseconds];
self.stopLabelMilli.text = timerOutputMilli;
}
}
-(void) setTimer{
Countdown = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timerRun) userInfo:nil repeats:YES];
CountdownMilli = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(timerRunMilli) userInfo:nil repeats:YES];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.start.enabled = YES;
self.stop.enabled = NO;
self.reset.enabled = NO;
}
- (IBAction)start:(id)sender{
if(pause == NO){
[self setTimer];
}
pause = NO;
self.start.enabled = NO;
self.stop.enabled = YES;
self.reset.enabled = YES;
}
- (IBAction)stop:(id)sender{
pause = YES;
self.start.enabled = YES;
self.stop.enabled = NO;
self.reset.enabled = YES;
}
- (IBAction)reset:(id)sender{
[Countdown invalidate];
Countdown = nil;
[CountdownMilli invalidate];
CountdownMilli = nil;
self.stopLabelHour.text = #"0";
self.stopLabelMin.text = #"00";
self.stopLabel.text = #"00";
self.stopLabelMilli.text = #"00";
overall = 0;
overallMilli = 0;
pause = NO;
self.start.enabled = YES;
self.stop.enabled = NO;
self.reset.enabled = NO;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark iAd Delegate Mathods
-(void)bannerViewDidLoadAd:(ADBannerView *)banner{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
[banner setAlpha:1];
[UIView commitAnimations];
}
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
[banner setAlpha:0];
[UIView commitAnimations];
}
#end

You shouldn't keep the timer running in the view that isn't on display. When the view disappears the timer should be stopped and when the view appears (if the timer should be running) the timer should be restarted.
To do this, you should be using NSDate to record when the timer was started so that you can calculate how long it's been running for. The only reason you need to keep the timer running really is to process overall = overall - 1;.
Now, the above is more complex, and you need to add more logic into how you handle pause (there are other answers to pause with NSTimer on SO). But, it's a lot cleaner and it's more accurate (the timer fire rate isn't 100% guaranteed).

Related

Getting a current value from UIProgressView, and triggering an event when a threshold is met

I have several UIProgressViews that read the voltage of an external device attached to the iOS device. The view scales it from 0-5 volts and I wanted to know if there was a way to retrieve the current progress/voltage of the UIProgressView and compare it to a threshold that is input by a user. Once this threshold is surpassed; a method I have written should be called.
The problem isn't necessarily the comparison part or calling the method. I am having trouble retrieving a live update of what the current value of the progressview is.
Thanks for your time.
EDIT FOR PART II:
So the problem is I did not code this and it is code pertaining to a certain product called the Nanospark board. This board is an input/output control board for factory systems that is run by various iOS devices.
I cannot quite seem to figure out what the previous coder did within this class:
//
// AnalogVC.m
// NanosparkController
//
#import "AnalogVC.h"
#import "AppDelegate.h"
#interface InputItem : NSObject
#property (weak,nonatomic) UISwitch *onSwitch;
#property (weak,nonatomic) UIProgressView *progressView;
#property (weak,nonatomic) UILabel *valueLabel;
#end
#implementation InputItem
AppDelegate *appDelegate;
+ (id)itemWithSwitch:(id)temp progress:(id)progress label:(id)label
{
InputItem *item = [[InputItem alloc] init];
item.onSwitch = temp;
item.progressView = progress;
item.valueLabel = label;
return item;
}
- (void)setDisconnected
{
self.onSwitch.on = NO;
self.onSwitch.enabled = NO;
self.valueLabel.text = #"0.000 v";
self.progressView.progress = 0;
}
- (void)setOn
{
self.onSwitch.on = YES;
self.onSwitch.enabled = YES;
self.valueLabel.text = #"0.000 v";
self.progressView.progress = 0;
[appDelegate watchPins:#"testing ON"];
}
- (void)setOff
{
self.onSwitch.on = NO;
self.onSwitch.enabled = YES;
self.valueLabel.text = #"0.000 v";
self.progressView.progress = 0;
[appDelegate watchPins:#"testing OFF"];
}
- (void)setValue:(double)value
{
if (self.onSwitch.on)
{
self.valueLabel.text = [NSString stringWithFormat:#"%0.3f v",value];
self.progressView.progress = value/5.0;
if(value > 0.8){
[appDelegate watchPins:#"testing VALUE"];
}
}
}
#end
#interface AnalogVC ()
{
NSArray *_inputItems;
AppDelegate *appDelegate;
NSMutableArray *channel0Values;
UIColor *custom1;
UIColor *custom2;
UIColor *custom3;
UIColor *custom4;
}
#property (nonatomic) NCBoardManager *manager;
#property (weak,nonatomic) IBOutlet UISwitch *inputSwitch0;
#property (weak,nonatomic) IBOutlet UISwitch *inputSwitch1;
#property (weak,nonatomic) IBOutlet UISwitch *inputSwitch2;
#property (weak,nonatomic) IBOutlet UISwitch *inputSwitch3;
#property (weak,nonatomic) IBOutlet UISwitch *inputSwitch4;
#property (weak,nonatomic) IBOutlet UISwitch *inputSwitch5;
#property (weak,nonatomic) IBOutlet UIProgressView *inputProgress0;
#property (weak,nonatomic) IBOutlet UIProgressView *inputProgress1;
#property (weak,nonatomic) IBOutlet UIProgressView *inputProgress2;
#property (weak,nonatomic) IBOutlet UIProgressView *inputProgress3;
#property (weak,nonatomic) IBOutlet UIProgressView *inputProgress4;
#property (weak,nonatomic) IBOutlet UIProgressView *inputProgress5;
#property (weak,nonatomic) IBOutlet UILabel *inputValue0;
#property (weak,nonatomic) IBOutlet UILabel *inputValue1;
#property (weak,nonatomic) IBOutlet UILabel *inputValue2;
#property (weak,nonatomic) IBOutlet UILabel *inputValue3;
#property (weak,nonatomic) IBOutlet UILabel *inputValue4;
#property (weak,nonatomic) IBOutlet UILabel *inputValue5;
#property (weak,nonatomic) IBOutlet UISlider *outputSlider0;
#property (weak,nonatomic) IBOutlet UISlider *outputSlider1;
#property (weak,nonatomic) IBOutlet UIStepper *outputStepper0;
#property (weak,nonatomic) IBOutlet UIStepper *outputStepper1;
#property (weak,nonatomic) IBOutlet UILabel *outputValue0;
#property (weak,nonatomic) IBOutlet UILabel *outputValue1;
- (IBAction)inputChannelChanged:(UISwitch *)sender;
- (IBAction)outputSliderMoved:(UISlider *)sender;
- (IBAction)outputSliderStopped:(UISlider *)sender;
- (IBAction)outputStepperChanged:(UIStepper *)sender;
#end
#implementation AnalogVC{}
//////////////////////////////
#pragma mark View Lifecycle
//////////////////////////////
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Analog VC loaded");
_inputItems = #[[InputItem itemWithSwitch:_inputSwitch0 progress:_inputProgress0 label:_inputValue0],
[InputItem itemWithSwitch:_inputSwitch1 progress:_inputProgress1 label:_inputValue1],
[InputItem itemWithSwitch:_inputSwitch2 progress:_inputProgress2 label:_inputValue2],
[InputItem itemWithSwitch:_inputSwitch3 progress:_inputProgress3 label:_inputValue3],
[InputItem itemWithSwitch:_inputSwitch4 progress:_inputProgress4 label:_inputValue4],
[InputItem itemWithSwitch:_inputSwitch5 progress:_inputProgress5 label:_inputValue5]];
_manager = [NCBoardManager sharedBoardManager];
__unsafe_unretained AnalogVC *vc = self;
[_manager setAnalogInputHandling:dispatch_get_main_queue()
filter:^(NCAnalogInputs *inputs){ return YES; }
handler:^(NCAnalogInputs *inputs){ [vc setAnalogInputs:inputs]; }];
// Register for notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(boardConnected:)
name:CONNECTED_NOTIFICATION
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(boardDisconnected:)
name:DISCONNECTED_NOTIFICATION
object:nil];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self updateAnalogInputs];
[self updateAnalogOutputs];
custom1 = [UIColor whiteColor];
custom2 = [UIColor darkGrayColor];
custom3 = [UIColor blackColor];
custom4 = [UIColor colorWithRed:.97 green:.97 blue:.588 alpha:1.0];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = self.view.bounds;
gradient.colors = [NSArray arrayWithObjects:(id)[custom2 CGColor], (id)[custom1 CGColor], (id)[custom2 CGColor], nil];
gradient.startPoint = CGPointMake(0.5, 0);
gradient.endPoint = CGPointMake(0.5, 1.0);
gradient.locations = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:0.5], [NSNumber numberWithFloat:1.0], nil];
[self.view.layer insertSublayer:gradient atIndex:0];
[self.inputSwitch0 setOnTintColor:custom4];
[self.inputSwitch1 setOnTintColor:custom4];
[self.inputSwitch2 setOnTintColor:custom4];
[self.inputSwitch3 setOnTintColor:custom4];
[self.inputSwitch4 setOnTintColor:custom4];
[self.inputSwitch5 setOnTintColor:custom4];
[self.inputSwitch0 setTintColor:custom3];
[self.inputSwitch1 setTintColor:custom3];
[self.inputSwitch2 setTintColor:custom3];
[self.inputSwitch3 setTintColor:custom3];
[self.inputSwitch4 setTintColor:custom3];
[self.inputSwitch5 setTintColor:custom3];
self.inputProgress0.trackTintColor = custom3;
self.inputProgress1.trackTintColor = custom3;
self.inputProgress2.trackTintColor = custom3;
self.inputProgress3.trackTintColor = custom3;
self.inputProgress4.trackTintColor = custom3;
self.inputProgress5.trackTintColor = custom3;
self.inputProgress0.progressTintColor = custom4;
self.inputProgress1.progressTintColor = custom4;
self.inputProgress2.progressTintColor = custom4;
self.inputProgress3.progressTintColor = custom4;
self.inputProgress4.progressTintColor = custom4;
self.inputProgress5.progressTintColor = custom4;
self.outputSlider0.minimumTrackTintColor = custom4;
self.outputSlider1.minimumTrackTintColor = custom4;
self.outputSlider0.maximumTrackTintColor = custom3;
self.outputSlider1.maximumTrackTintColor = custom3;
self.outputSlider0.thumbTintColor = custom3;
self.outputSlider1.thumbTintColor = custom3;
if(_manager.isBoardConnected)
{
self.outputStepper0.tintColor = custom4;
self.outputStepper1.tintColor = custom4;
self.outputStepper0.enabled = TRUE;
self.outputStepper1.enabled = TRUE;
self.outputSlider0.enabled = TRUE;
self.outputSlider1.enabled = TRUE;
}
else
{
self.outputStepper0.tintColor = custom2;
self.outputStepper1.tintColor = custom2;
self.outputStepper0.enabled = FALSE;
self.outputStepper1.enabled = FALSE;
self.outputSlider0.enabled = FALSE;
self.outputSlider1.enabled = FALSE;
}
}
//////////////////////////////
#pragma mark Rotation Calls
//////////////////////////////
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotate
{
return FALSE;
}
//////////////////////////
#pragma mark Board Calls
//////////////////////////
- (void)boardConnected:(NSNotification *)notification
{
[self updateAnalogInputs];
[self updateAnalogOutputs];
self.outputStepper0.enabled = TRUE;
self.outputStepper1.enabled = TRUE;
self.outputSlider0.enabled = TRUE;
self.outputSlider1.enabled = TRUE;
self.outputStepper0.tintColor = custom4;
self.outputStepper1.tintColor = custom4;
}
- (void)boardDisconnected:(NSNotification *)notification
{
[self updateAnalogInputs];
[self updateAnalogOutputs];
self.outputStepper0.enabled = FALSE;
self.outputStepper1.enabled = FALSE;
self.outputSlider0.enabled = FALSE;
self.outputSlider1.enabled = FALSE;
self.outputStepper0.tintColor = custom2;
self.outputStepper1.tintColor = custom2;
}
- (void)updateAnalogInputs
{
uint8_t channel = self.manager.analogInputChannels;
switch (self.manager.analogInputStatus)
{
case NCInputConnected:
// Check if channels we left on
if (channel) self.manager.analogInputChannels = 0;
[_inputItems makeObjectsPerformSelector:#selector(setOff)];
break;
case NCInputDisconnected:
[_inputItems makeObjectsPerformSelector:#selector(setDisconnected)];
break;
case NCInputLiveUpdating:
for (InputItem *item in _inputItems)
{
//if (channel & 1) [item setOn];
//else [item setOff];
channel >>= 1;
}
break;
case NCInputSampling:
[_inputItems makeObjectsPerformSelector:#selector(setDisconnected)];
break;
case NCInputTransfering:
[_inputItems makeObjectsPerformSelector:#selector(setDisconnected)];
break;
}
}
- (void)setAnalogInputs:(NCAnalogInputs *)inputs
{
int i = 0;
uint8_t channels = inputs.channels;
for (InputItem *item in _inputItems)
{
if (channels & 1)
{
[item setValue:[inputs valueForChannel:i]];
}
channels >>= 1;
i++;
}
}
- (void)updateAnalogOutputs
{
BOOL connected = [self.manager isBoardConnected];
self.outputSlider0.value = self.manager.analogOutput0;
self.outputSlider0.enabled = connected;
self.outputStepper0.value = self.outputSlider0.value * 1000;
self.outputStepper0.enabled = connected;
self.outputValue0.text = [NSString stringWithFormat:#"%0.3f v",self.outputSlider0.value];
self.outputSlider1.value = self.manager.analogOutput1;
self.outputSlider1.enabled = connected;
self.outputStepper1.value = self.outputSlider1.value * 1000;
self.outputStepper1.enabled = connected;
self.outputValue1.text = [NSString stringWithFormat:#"%0.3f v",self.outputSlider1.value];
}
///////////////////////////////
#pragma mark IBAction Methods
///////////////////////////////
- (IBAction)inputChannelChanged:(UISwitch *)sender
{
NSLog(#"TEST");
InputItem *item = [_inputItems objectAtIndex:sender.tag];
uint8_t channels = self.manager.analogInputChannels;
if (sender.on)
{
channels |= (1 << sender.tag);
[item setOn];
}
else
{
channels &= ~(1 << sender.tag);
[item setOff];
}
if (!self.manager.analogInputChannels) [self.manager startAnalogLiveUpdating];
else if(!channels) [self.manager stopAnalogLiveUpdating];
self.manager.analogInputChannels = channels;
}
- (IBAction)outputSliderMoved:(UISlider *)sender
{
if (!sender.tag)
{
self.manager.analogOutput0 = sender.value;
self.outputValue0.text = [NSString stringWithFormat:#"%0.3f v",sender.value];
}
else
{
self.manager.analogOutput1 = sender.value;
self.outputValue1.text = [NSString stringWithFormat:#"%0.3f v",sender.value];
}
}
- (IBAction)outputSliderStopped:(UISlider *)sender
{
if (!sender.tag)
{
self.manager.analogOutput0 = sender.value;
self.outputStepper0.value = round(sender.value * 1000.0);
self.outputValue0.text = [NSString stringWithFormat:#"%0.3f v",self.outputStepper0.value/1000.0];
}
else
{
self.manager.analogOutput1 = sender.value;
self.outputStepper1.value = round(sender.value * 1000.0);
self.outputValue1.text = [NSString stringWithFormat:#"%0.3f v",self.outputStepper1.value/1000.0];
}
}
- (IBAction)outputStepperChanged:(UIStepper *)sender
{
float value = sender.value/1000.0;
if (!sender.tag)
{
self.manager.analogOutput0 = value;
self.outputSlider0.value = value;
self.outputValue0.text = [NSString stringWithFormat:#"%0.3f v",value];
}
else
{
self.manager.analogOutput1 = sender.value/1000.0;
self.outputSlider1.value = value;
self.outputValue1.text = [NSString stringWithFormat:#"%0.3f v",value];
}
}
#end
The problem I am having is I cannot figure out how to take values to and from the UIProgressViews that are on the storyboard (which is, like you said, a trivial concept). However with this set up it is rather convoluted.
Second problem is that; I am not sure if there is a way I can debug this as the application only runs when the external device (the nanospark controller board) is connected to the iPod.
The last but final problem I am having is that I am assuming the IBAction InputChannelChanged is being called (cannot debug this regularly with a breakpoint as aforementioned because it requires the external device to run the application), but when I run the application it does everything it should and the buttons react correctly to what the original software developer had coded.
This means that if I add my texting method to the IBAction (by adding [appDelegate watchPins#"TEST"]) it does not send the text to the user, but the buttons do still do what they should have done in concordance to the previous developers' aspirations.... this implies that the IBAction method is indeed being called... but then why isn't my text going through? I know that [appDelegate watchPins:#"TEST"]; should work as I have used it within several of his other classes.
Here is a screenshot displaying the UI of the AnalogVC.m:
http://i.stack.imgur.com/NNpZk.png
Do not feel obligated to answer all of these questions it's just I felt it necessary to provided all three for greater context of the problem. Thanks and sorry for the TL;DR.
EDIT 2: I'd upload the image but I do not have the required minimum reputation.
EDIT 3: I have tried to add another IBAction just to see if the buttons react to that; still nothing even if I copied the exact code from the other working classes.
Solution 1:
You need to call your method when you update the UIProgressView I assume that use are using the setProgress: animated: method somewhere in your code to update the progress view. If so, try this code in the method in which you update the UIProgressView:
float myVoltageFromDevice = self.deviceInput / 5.0; //this can be whatever your input is mapped to 0.0...1.0
//the self.device input variable should be the input from the external device.
if(myFloatFromDevice > myThreshold){ //set my threshold to whatever you would like.
[self doAction]; //do whatever you need to do when the value is surpassed
}else{
[myProgressView setProgress:myVoltageFromDevice animated: NO];
}
Edit:
I commented in the code above //this can be whatever your input is mapped to 0.0...1.0. Just in case this isn't clear, to achieve mapping you would do:
float myVoltageFromDevice = self.deviceInput / 5.0;
because the device input variable should be a value from 0-5 as you said in the OP. This makes the value from 0.0-1.0 which is the range of values that UIProgressView will accept.
Solution 2:
If can't pull off the above (which you really should be able to do), you should use Key Value Observing (KVO) which is detailed in this apple developer doc.
Edit 2:
The code you posted is quite complicated, but I believe that the method that you need to edit is - (void)setAnalogInputs:(NCAnalogInputs *)inputs try changing some of the code to this:
for (InputItem *item in _inputItems)
{
if (channels & 1)
{
if([inputs valueForChannel:i] > myThreshold){
[self doAction]; //Do your action here.
}else{
[item setValue:[inputs valueForChannel:i]];
}
}
channels >>= 1;
i++;
}

Cannot compile with error, not sure what to do

I am Getting error message as follows...
"2014-01-28 21:17:56.878 Higher or Lower 2[5869:70b] * Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key enterButoonOut.'
* First throw call stack:"
//
// ViewController.m
// Higher or Lower 2
//
// Created by Michael Goedken on 1/27/14.
// Copyright (c) 2014 Michael Goedken. All rights reserved.
//
/
// Created by Michael Goedken on 1/27/14.
// Copyright (c) 2014 Michael Goedken. All rights reserved.
//
#import "ViewController.h"
int answer = 0;
int guess = 0;
int turn = 0;
BOOL timeStarted = NO;
#interface ViewController ()
#end
#implementation ViewController
- (IBAction)enterButton:(id)sender {
NSString *input = _labelGuess.text;
guess = [input intValue];
_previousLabel.text = [NSString stringWithFormat:#"%d",guess];
_labelGuess.text=#"";
turn++;
_guessesLabel.text = [NSString stringWithFormat:#"%d",turn];
if (timeStarted == NO){
seconds = 0;
timer = [NSTimer scheduledTimerWithTimeInterval:.001 target:self
selector:#selector(countUp) userInfo:nil repeats:YES];
}
timeStarted = YES;
if (guess < 1 || guess > 100){
_correct.hidden = YES;
_lower.hidden = YES;
_higher.hidden = YES;
_chooseNumber.hidden = YES;
_outOfRange.hidden = NO;
}
else if (guess > answer) {
_lower.hidden = NO;
_higher.hidden = YES;
_chooseNumber.hidden = YES;
_correct.hidden = YES;
_outOfRange.hidden = YES;
}
else if (guess < answer) {
_lower.hidden = YES;
_higher.hidden = NO;
_chooseNumber.hidden = YES;
_correct.hidden = YES;
_outOfRange.hidden = YES;
}
else {
_correct.hidden = NO;
_lower.hidden = YES;
_higher.hidden = YES;
_chooseNumber.hidden = YES;
_outOfRange.hidden = YES;
[timer invalidate];
_nextButtonOut.hidden = NO;
_enterButtonOut.hidden = YES;
_labelGuess.hidden = YES;
}
}
-(void) countUp {
milliSeconds ++;
seconds = milliSeconds / 1000;
minutes = seconds / 60;
remainingSeconds = seconds % 60;
remainingMilliSeconds = milliSeconds % 1000;
if (minutes > 0) {
_timerLabel.text = [NSString stringWithFormat:#"%2d:%.2d", minutes, remainingSeconds];
}
else {
_timerLabel.text = [NSString stringWithFormat:#"%2d:%.2d.%.3d", minutes,
remainingSeconds, remainingMilliSeconds];
}
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[_labelGuess resignFirstResponder];
}
- (void)viewDidLoad
{
[super viewDidLoad];
_labelGuess.keyboardType = UIKeyboardTypeNumberPad;
_higher.hidden = YES;
_lower.hidden = YES;
_correct.hidden = YES;
_outOfRange.hidden = YES;
answer = arc4random() % 100 + 1;
_nextButtonOut.hidden = YES;
NSLog(#"Answer %i", answer);
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)nextButton:(id)sender {
_correct.hidden = YES;
_lower.hidden = YES;
_higher.hidden = YES;
_chooseNumber.hidden = YES;enter code here
_outOfRange.hidden = YES;
_labelGuess.hidden = YES;
_guessesLabel.hidden = YES;
_previousLabel.hidden = YES;
_timerLabel.hidden = YES;
_nextButtonOut.hidden = YES;
_enterButtonOut.hidden = YES;
_background.hidden = YES;
_guesses.hidden = YES;
_previous.hidden = YES;
}
#end
//
// ViewController.h
// Higher or Lower 2
//
// Created by Michael Goedken on 1/27/14.
// Copyright (c) 2014 Michael Goedken. All rights reserved.
//
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
NSTimer *timer;
int seconds;
int minutes;
int remainingSeconds;
int milliSeconds;
int remainingMilliSeconds;
}
#property (weak, nonatomic) IBOutlet UIImageView *chooseNumber;
#property (weak, nonatomic) IBOutlet UITextField *labelGuess;
#property (weak, nonatomic) IBOutlet UIImageView *higher;
#property (weak, nonatomic) IBOutlet UIImageView *lower;
#property (weak, nonatomic) IBOutlet UIImageView *correct;
#property (weak, nonatomic) IBOutlet UIImageView *outOfRange;
#property (weak, nonatomic) IBOutlet UILabel *previousLabel;
#property (weak, nonatomic) IBOutlet UILabel *timerLabel;
#property (weak, nonatomic) IBOutlet UIButton *nextButtonOut;
#property (weak, nonatomic) IBOutlet UIButton *enterButtonOut;
#property (weak, nonatomic) IBOutlet UIImageView *background;
#property (weak, nonatomic) IBOutlet UILabel *previous;
#property (weak, nonatomic) IBOutlet UILabel *guessesLabel;
#property (weak, nonatomic) IBOutlet UILabel *guesses;
- (IBAction)nextButton:(id)sender;
- (IBAction)enterButton:(id)sender;
#end
I normally get this error message when one of a few things happens.
1) I have misspelled the value for segue.identifier as I'm about to segue to another module (not sure this applies in your case, but that is where it always gets me).
2) If you make changes to a storyboard, then go delete the value in code, the connection does not get eliminated in your storyboard and you have to manually go in and delete the link from within storyboard. To check, just right click (or ctrl click) on each element in a storyboard and note the connections.
My guess is if you look at that button in the storyboard, you will see "enterButoonOut" instead of "enterButtonOut"
Hope this helps!
Glenn
You have misspelled enterButoonOut and it must be enterButtonOut as per your declaration:
#property (weak, nonatomic) IBOutlet UIButton *enterButtonOut;

objective c delegates

My program displays images with a timer. I want the user to be able to adjust the timer by using a UISlider.
I have a Deck class, which delegates and listens to another delegate 'SpeedSliderDelegate'. I want my Deck class to listen for changes from the SpeedSliderDelegate and update a value.
How do I set my Deck.m model to listen to SpeedSliderDelegate...(just after if(self = [super init] in Deck.m)
SpeedSliderDelegate.h
#protocol SpeedSliderDelegate <NSObject>
-(void)setSpeed:(float)currentSpeed;
#end
Deck.h
#import "SpeedSliderDelegate.h"
#import <Foundation/Foundation.h>
#import "Card.h"
#protocol DeckLooperDelegate <NSObject>
-(void)cardHasChangedTo:card1 aCard2:(Card *)card2 totalCount:(NSInteger)totalCount stopTimer:(NSTimer*)stopTimer cards:(NSArray *)cards;
#end
#interface Deck : NSObject <SpeedSliderDelegate>
#property (nonatomic, retain)NSMutableArray *cards;
#property (nonatomic, retain)NSTimer *timer;
#property (nonatomic, retain)id <DeckLooperDelegate> delegate;
#property (nonatomic)NSInteger total;
#property (nonatomic) float testSpeed;
- (NSInteger) cardsRemaining;
- (void) startTimerLoop;
#end
Deck.m
#import "Deck.h"
#import "Card.h"
#implementation Deck
#synthesize cards;
#synthesize timer;
#synthesize delegate;
#synthesize total, testSpeed;
- (id) init
{
if(self = [super init])
{
//self.delegate = self something like this...
cards = [[NSMutableArray alloc] init];
NSInteger aCount, picNum = 0;
for(int suit = 0; suit < 4; suit++)
{
for(int face = 1; face < 14; face++, picNum++)
{
if (face > 1 && face < 7)
aCount = 1;
else if (face > 6 && face < 10)
aCount = 0;
else
aCount = -1;
NSString* imagePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"card_%d", picNum] ofType:#"png"];
UIImage* theImage = [[UIImage alloc] initWithContentsOfFile:imagePath];
Card *card = [[Card alloc] initWithFaceValue:(NSInteger)face
countValue:(NSInteger)aCount
suit:(Suit)suit
cardImage:(UIImage *)theImage];
[cards addObject:card];
}
}
}
return self;
}
-(void)setSpeed:(float)currentSpeed
{
testSpeed = currentSpeed;
}
-(void)startTimerLoop
{
if (!timer)
{
timer = [NSTimer scheduledTimerWithTimeInterval:testSpeed target:self
selector:#selector(timerEvent:) userInfo:nil repeats:YES ];
NSLog(#"Timer started!!!");
}
}
-(void)timerEvent:(NSTimer*)timer
{
srand(time(nil));
int index = rand()%[cards count];
Card *randomCard =[cards objectAtIndex:index];
[cards removeObjectAtIndex:index];
NSLog(#"%#" ,randomCard);
int index1 = rand()%[cards count];
Card *randomCard1 =[cards objectAtIndex:index1];
[cards removeObjectAtIndex:index1];
NSLog(#"%#" ,randomCard1);
total += (randomCard.countValue + randomCard1.countValue);
[self.delegate cardHasChangedTo:randomCard aCard2:randomCard1 totalCount:total stopTimer:self.timer cards:cards];
if ([cards count] == 0)
{
[self.timer invalidate];
self.timer = nil;
}
}
- (NSInteger) cardsRemaining
{
return [cards count];
}
- (NSString *) description
{
NSString *desc = [NSString stringWithFormat:#"Deck with %d cards\n",
[self cardsRemaining]];
return desc;
}
#end
GameViewController.h
#import "Deck.h"
#import "SpeedSliderDelegate.h"
#interface GameViewController : UIViewController <DeckLooperDelegate>
#property (nonatomic, retain) IBOutlet UIImageView *cardDisplay, *cardDisplay1;
#property (weak, nonatomic) IBOutlet UILabel *cardName, *cardName1;
#property (weak, nonatomic) IBOutlet UILabel *cardCount, *cardCount1;
#property (weak, nonatomic) IBOutlet UILabel *totalCount;
#property (nonatomic)int stop1;
#property (weak, nonatomic) IBOutlet UIButton *stopButton;
#property (weak, nonatomic) IBOutlet UIButton *restartButton;
#property (weak, nonatomic) IBOutlet UIButton *homeButton;
#property (weak, nonatomic) IBOutlet UISlider *speed;
#property (nonatomic, retain) id <SpeedSliderDelegate> delegate;
- (IBAction)start:(id)sender;
- (IBAction)stop:(id)sender;
- (IBAction)hideShow:(id)sender;
- (IBAction)homeAction:(id)sender;
#end
GameViewController.m
#import <QuartzCore/QuartzCore.h>
#import "GameViewController.h"
#import "Deck.h"
#implementation GameViewController
#synthesize cardDisplay, cardDisplay1, cardName, cardName1, cardCount, cardCount1, totalCount, stop1, stopButton, restartButton, homeButton, speed, delegate;
- (void)viewDidLoad
{
[super viewDidLoad];
Deck *deck = [[Deck alloc]init];
NSLog(#"%#", deck);
for (id cards in deck.cards)
{
NSLog(#"%#", cards);
}
deck.delegate = self;
[deck startTimerLoop];
cardDisplay.layer.cornerRadius = 7;
cardDisplay.clipsToBounds = YES;
cardDisplay1.layer.cornerRadius = 7;
cardDisplay1.clipsToBounds = YES;
[restartButton setHidden:YES];
[delegate setSpeed:speed.value];
}
//#pragma mark - DeckDelegate
-(void)cardHasChangedTo:(Card *)card1 aCard2:(Card *)card2 totalCount:(NSInteger)totalC stopTimer:(NSTimer *)stopTimer cards:(NSArray *)cards
{
[self.cardDisplay setImage:card1.cardImage];
[self.cardDisplay1 setImage:card2.cardImage];
self.cardName.text = card1.description;
self.cardName1.text = card2.description;
self.cardCount.text = [NSString stringWithFormat:#"%d", card1.countValue];
self.cardCount1.text = [NSString stringWithFormat:#"%d", card2.countValue];
self.totalCount.text = [NSString stringWithFormat:#"%d", totalC];
if (stop1 == 86)
{
[stopTimer invalidate];
stopTimer = nil;
}
if ([cards count] == 0)
{
[restartButton setHidden:NO];
}
}
- (IBAction)start:(id)sender
{
stop1 = 85;
[cardDisplay setHidden:YES];
[cardDisplay1 setHidden:YES];
self.totalCount.text = #"0";
self.cardCount.text = #"0";
self.cardCount1.text = #"0";
self.cardName.text = #"";
self.cardName1.text = #"";
Deck *deck = [[Deck alloc]init];
[NSTimer scheduledTimerWithTimeInterval:2 target:self
selector:#selector(cardDisplayDelay:) userInfo:nil repeats:NO];
NSLog(#"%#", deck);
deck.delegate = self;
[deck startTimerLoop];
cardDisplay.layer.cornerRadius = 7;
cardDisplay.clipsToBounds = YES;
cardDisplay1.layer.cornerRadius = 7;
cardDisplay1.clipsToBounds = YES;
[restartButton setHidden:YES];
}
- (IBAction)stop:(id)sender
{
stop1 = 86; //cancelled
[NSTimer scheduledTimerWithTimeInterval:2 target:self
selector:#selector(restartButtonDelay:) userInfo:nil repeats:NO];
}
-(void)restartButtonDelay:(NSTimer*)timer
{
[restartButton setHidden:NO];
}
-(void)cardDisplayDelay:(NSTimer*)timer
{
[cardDisplay setHidden:NO];
[cardDisplay1 setHidden:NO];
}
- (IBAction)hideShow:(id)sender
{
if ([cardCount isHidden])
{
[cardCount setHidden:NO];
[cardCount1 setHidden:NO];
[totalCount setHidden:NO];
}
else
{
[cardCount setHidden:YES];
[cardCount1 setHidden:YES];
[totalCount setHidden:YES];
}
}
- (IBAction)homeAction:(id)sender
{
stop1 = 86; //cancelled
}
#end
In the updating class .h
#protocol DoSomethingDelegate <NSObject>
-(void)doSomething;
#end
#property (assign, nonatomic) id <DoSomethingDelegate> delegate;
In the updating class .m
-(void)doSomethingSomewhereElse {
if (self.delegate != nil && [self.delegate respondsToSelector:#selector(doSomething)]) {
[self.delegate performSelector:#selector(doSomething)];
}
} else {
NSLog(#"Delgate doesn't implement doSomething");
}
}
In the receiving class' .h:
Conform to protocol <DoSomethingDelegate>
#interface myDoSomethingClass : NSObject <DoSomethingDelegate>
...
Implement the delegate method in the receiving class' .m:
-(void)someInit{
//set the delegate to self
}
In the view controller .m
-(void)doSomething{
NSLog(#"The delegate told me to do this!");
}
The deck is not its own delegate. Right now your code says that a Deck is a SpeedSliderDelegate, and that a Deck's delegate is a DeckLooperDelegate.
If you always need a delegate for Deck, you can do it this way:
- (id) initWithDelegate:(id<DeckLooperDelegate>)delegate {
if (self = [super init]) {
self.delegate = delegate;
cards = [[NSMutableArray alloc] init];
NSInteger aCount, picNum = 0;
// etc etc etc
}
}
Then, in the DeckLooperDelegate that creates the deck, you call it like this:
Deck *deck = [[Deck alloc] initWithDelegate:self];
Then you want your speed slider to set the deck as its delegate.
mySpeedSlider.delegate = deck;
Now mySpeedSlider can call [delegate setSpeed:] to change the deck's speed.

How to fix: Incomplete Implementation

How can I fix the problem of Incomplete Implementation?
View of Controller.m :
#import "Quiz_GameViewController.h"
#implementation Quiz_GameViewController
#synthesize theQuestion, timer, theScore, theLives, answerOne, answerTwo, answerThree, answerFour, theQuiz
;
-(void)askQuestion
{
// Unhide all the answer buttons.
[answerOne setHidden:NO];
[answerTwo setHidden:NO];
[answerThree setHidden:NO];
[answerFour setHidden:NO];
// Set the game to a "live" question (for timer purposes)
questionLive = YES;
// Set the time for the timer
time = 8.0;
// Go to the next question
questionNumber = questionNumber + 1;
// We get the question from the questionNumber * the row that we look up in the array.
NSInteger row = 0;
if(questionNumber == 1)
{
row = questionNumber - 1;
}
else
{
row = ((questionNumber - 1) * 6);
}
// Set the question string, and set the buttons the the answers
NSString *selected = [theQuiz objectAtIndex:row];
NSString *activeQuestion = [[NSString alloc] initWithFormat:#"Question: %#", selected];
[answerOne setTitle:[theQuiz objectAtIndex:row+1] forState:UIControlStateNormal];
[answerTwo setTitle:[theQuiz objectAtIndex:row+2] forState:UIControlStateNormal];
[answerThree setTitle:[theQuiz objectAtIndex:row+3] forState:UIControlStateNormal];
[answerFour setTitle:[theQuiz objectAtIndex:row+4] forState:UIControlStateNormal];
rightAnswer = [[theQuiz objectAtIndex:row+5] intValue];
// Set theQuestion label to the active question
theQuestion.text = activeQuestion;
// Start the timer for the countdown
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(countDown) userInfo:nil repeats:YES];
[selected release];
[activeQuestion release];
}
-(void)updateScore
{
// If the score is being updated, the question is not live
questionLive = NO;
[timer invalidate];
// Hide the answers from the previous question
[answerOne setHidden:YES];
[answerTwo setHidden:YES];
[answerThree setHidden:YES];
[answerFour setHidden:YES];
NSString *scoreUpdate = [[NSString alloc] initWithFormat:#"Score: %d", myScore];
theScore.text = scoreUpdate;
[scoreUpdate release];
// END THE GAME.
NSInteger endOfQuiz = [theQuiz count];
if((((questionNumber - 1) * 6) + 6) == endOfQuiz)
{
// Game is over.
if(myScore > 0)
{
NSString *finishingStatement = [[NSString alloc] initWithFormat:#"Game Over!\nNice Game \nYou scored %i!", myScore];
theQuestion.text = finishingStatement;
[finishingStatement release];
}
else
{
NSString *finishingStatement = [[NSString alloc] initWithFormat:#"Game Over!\n You're terrible! \nYou scored %i.", myScore];
theQuestion.text = finishingStatement;
[finishingStatement release];
}
theLives.text = #"";
// Make button 1 appear as a reset game button
restartGame = YES;
[answerOne setHidden:NO];
[answerOne setTitle:#"Restart game!" forState:UIControlStateNormal];
}
else
{
// Give a short rest between questions
time = 3.0;
// Initialize the timer
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(countDown) userInfo:nil repeats:YES];
}
}
-(void)countDown
{
// Question live counter
if(questionLive==YES)
{
time = time - 1;
theLives.text = [NSString stringWithFormat:#"Time remaining: %i!", time];
if(time == 0)
{
// Loser!
questionLive = NO;
theQuestion.text = #"HAHA now you lost alot of points!";
myScore = myScore - 1000;
[timer invalidate];
[self updateScore];
}
}
// In-between Question counter
else
{
time = time - 1;
theLives.text = [NSString stringWithFormat:#"Next question coming in...%i!", time];
if(time == 0)
{
[timer invalidate];
theLives.text = #"";
[self askQuestion];
}
}
if(time < 0)
{
[timer invalidate];
}
}
- (IBAction)buttonOne
{
if(questionNumber == 0){
// This means that we are at the startup-state
// We need to make the other buttons visible, and start the game.
[answerTwo setHidden:NO];
[answerThree setHidden:NO];
[answerFour setHidden:NO];
[self askQuestion];
}
else
{
NSInteger theAnswerValue = 1;
[self checkAnswer:(int)theAnswerValue];
if(restartGame==YES)
{
// Create a restart game function.
}
}
}
- (IBAction)buttonTwo
{
NSInteger theAnswerValue = 2;
[self checkAnswer:(int)theAnswerValue];
}
- (IBAction)buttonThree
{
NSInteger theAnswerValue = 3;
[self checkAnswer:(int)theAnswerValue];
}
- (IBAction)buttonFour
{
NSInteger theAnswerValue = 4;
[self checkAnswer:(int)theAnswerValue];
}
// Check for the answer (this is not written right, but it runs)
-(void)checkAnswer:(int)theAnswerValue
{
if(rightAnswer == theAnswerValue)
{
theQuestion.text = #"Daaamn";
myScore = myScore + 50;
}
else
{
theQuestion.text = #"hahaha!";
myScore = myScore - 50;
}
[self updateScore];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
questionLive = NO;
restartGame = NO;
theQuestion.text = #"Think you can do it?";
theScore.text = #"Score:0";
theLives.text = #"";
questionNumber = 0;
myScore = 0;
myLives = 0;
[answerOne setTitle:#"I think i can!" forState:UIControlStateNormal];
[answerTwo setHidden:YES];
[answerThree setHidden:YES];
[answerFour setHidden:YES];
[self loadQuiz];
}
-(void)loadQuiz
{
// This is our forced-loaded array of quiz questions.
// FORMAT IS IMPORTANT!!!!
// 1: Question, 2 3 4 5: Answers 1-4 respectively, 6: The right answer
// THIS IS A TERRIBLE WAY TO DO THIS. I will figure out how to do nested arrays to make this better.
NSArray *quizArray = [[NSArray alloc] initWithObjects:#"Who is the president in USA?",#"Me",#"Obama",#"George Bush",#"Justin Bieber",#"2",
#"Capital in Norway?", #"Bergen", #"Trondheim", #"Oslo", #"Bærum", #"3",
#"The right answer is 3!", #"41", #"24", #"3", #"9", #"1",
#"Do I have a cat?", #"Yes", #"No", #"No, you have a dog", #"No, you have a flying hamster", #"4",
#"Baba", #"Daba jaba?", #"Laba daba haba?", #"Saba daba gaba?", #"Haba haba?", #"4",
nil];
self.theQuiz = quizArray;
[quizArray release];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)dealloc {
[theQuestion release];
[theScore release];
[theLives release];
[answerOne release];
[answerTwo release];
[answerThree release];
[answerFour release];
[theQuiz release];
[timer release];
[super dealloc];
}
#end
I'am new here and this is an example script from the internet...I use it to learn the language Objective-C and Cocoa...ViewController.h :
#import <UIKit/UIKit.h>
#interface Quiz_GameViewController : UIViewController {
IBOutlet UILabel *theQuestion;
IBOutlet UILabel *theScore;
IBOutlet UILabel *theLives;
IBOutlet UIButton *answerOne;
IBOutlet UIButton *answerTwo;
IBOutlet UIButton *answerThree;
IBOutlet UIButton *answerFour;
NSInteger myScore;
NSInteger myLives;
NSInteger questionNumber;
NSInteger rightAnswer;
NSInteger time;
NSArray *theQuiz;
NSTimer *timer;
BOOL questionLive;
BOOL restartGame;
}
#property (retain, nonatomic) UILabel *theQuestion;
#property (retain, nonatomic) UILabel *theScore;
#property (retain, nonatomic) UILabel *theLives;
#property (retain, nonatomic) UIButton *answerOne;
#property (retain, nonatomic) UIButton *answerTwo;
#property (retain, nonatomic) UIButton *answerThree;
#property (retain, nonatomic) UIButton *answerFour;
#property (retain, nonatomic) NSArray *theQuiz;
#property (retain, nonatomic) NSTimer *timer;
-(IBAction)buttonOne;
-(IBAction)buttonTwo;
-(IBAction)buttonThree;
-(IBAction)buttonFour;
-(void)checkAnswer;
-(void)askQuestion;
-(void)updateScore;
-(void)loadQuiz;
-(void)countDown;
#end
In your headerfile, you have declared the method -(void)checkAnswer, while in the .m file you have declared it -(void)checkAnswer:(int)theAnswerValue.
This means that your .m file is looking for a method -(void)checkAnswer, which does not exist, and it yields an Incomplete implementation warning. Simply change your declaration in the .h file to - (void)checkAnswer:(int)theAnswerValue, and you'll be fine.
See in .h you have (method with no parameters):
-(void)checkAnswer;
and in .m you have (method with one int parameter):
-(void)checkAnswer:(int)theAnswerValue
Incomplete Implementation means you declared something in .h but didn't implement that in .m.
The signature of checkAnswer is different in you .h and .m
in Quiz_GameViewController.h:
-(void)checkAnswer;
in Quiz_GameViewController.m
-(void)checkAnswer:(int)theAnswerValue
FIX : Change the Quiz_GameViewController.h to:
- (void)checkAnswer:(int)theAnswerValue,

Incorrect UITextfield is being edited

I just finished a tutorial on making my own keypad. So I took that knowledge and made a real simple App that adds two numbers with my own keypad. It is just two numbers. But when I tap on one textfield, the other textfield gets edited! I have enclosed my code, any help will be much appreciated. And thanks to #spacious for all previous help.
#import "KeyPad2ViewController.h"
#interface KeyPad2ViewController ()
#property (nonatomic) BOOL userIsEnteringANumber;
#end
#implementation KeyPad2ViewController
#synthesize numberOne;
#synthesize numberTwo;
#synthesize result;
#synthesize keyPad;
#synthesize userIsEnteringANumber;
#synthesize currentTextField;
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if ([numberOne isFirstResponder])
{
self.currentTextField = self.numberOne;
self.userIsEnteringANumber = NO;
}
else if ([numberTwo isFirstResponder])
{
self.currentTextField = self.numberTwo;
self.userIsEnteringANumber = NO;
}
return YES;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[numberOne setInputView:keyPad];
[numberTwo setInputView:keyPad];
numberOne.delegate = self;
numberTwo.delegate = self;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setNumberOne:nil];
[self setNumberTwo:nil];
[self setResult:nil];
[self setKeyPad:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
return YES;
}
}
- (IBAction)buttonPressed:(UIButton *)sender
{
NSString *button = [sender currentTitle];
NSRange decimalpoint = [self.currentTextField.text rangeOfString:#"."];
if (self.userIsEnteringANumber)
{
if ([button isEqualToString:#"."] && decimalpoint.location != NSNotFound)
{
self.currentTextField.text = self.currentTextField.text;
}else
self.currentTextField.text = [self.currentTextField.text stringByAppendingString:button];
}else
{
self.currentTextField.text = button;
self.userIsEnteringANumber = YES;
}
}
- (IBAction)backspacePressed:(UIButton *)sender
{
if (self.userIsEnteringANumber)
{
int positionOfDigitBeforeLastOne = self.currentTextField.text.length -1;
if (self.currentTextField.text.length > 0)
{
self.currentTextField.text = [self.currentTextField.text substringToIndex:positionOfDigitBeforeLastOne];
}
if (self.currentTextField.text.length == 0)
self.currentTextField.text = #"";
}
}
- (IBAction)clearPressed:(id)sender
{
currentTextField.text = [NSString stringWithFormat:#""];
}
- (IBAction)enterPressed:(UIButton *)sender
{
[self hideKeyPad];
}
- (IBAction)signPressed:(UIButton *)sender
{
NSString *negativeNumber = #"-";
NSString *firstCharInDisplay = #"";
if (self.userIsEnteringANumber)
{
firstCharInDisplay = [self.currentTextField.text substringToIndex:1];
if ([firstCharInDisplay isEqualToString:#"-"])
{
self.currentTextField.text = [self.currentTextField.text substringFromIndex:1];
}else {
negativeNumber = [negativeNumber stringByAppendingString:self.currentTextField.text];
self.currentTextField.text = negativeNumber;
}
}
}
- (IBAction)add:(UIButton *)sender
{
float a = [[numberOne text] floatValue];
float b = [[numberTwo text] floatValue];
float c = a + b;
[result setText:[NSString stringWithFormat:#"%.2f", c]];
}
- (void)showKeyPad
{
[UIView beginAnimations:#"animateView" context:nil];
[UIView setAnimationDuration:0.3];
CGRect keypadview = CGRectMake(0, 270, 320, 190); // puts keyboard on screen
keyPad.frame = keypadview;
keyPad.alpha = 1.0;
[UIView commitAnimations];
}
- (void)hideKeyPad
{
[UIView beginAnimations:#"animateView" context:nil];
[UIView setAnimationDuration:0.3];
CGRect keypadview = CGRectMake(0, 640, 320, 190); // puts keyboard off screen
keyPad.frame = keypadview;
keyPad.alpha = 1.0;
[UIView commitAnimations];
}
#end
and my .h file is
#import <UIKit/UIKit.h>
#interface KeyPad2ViewController : UIViewController <UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UITextField *numberOne;
#property (weak, nonatomic) IBOutlet UITextField *numberTwo;
#property (weak, nonatomic) IBOutlet UILabel *result;
#property (strong, nonatomic) IBOutlet UIView *keyPad;
#property (weak, nonatomic) UITextField *currentTextField;
- (IBAction)buttonPressed:(UIButton *)sender;
- (IBAction)backspacePressed:(UIButton *)sender;
- (IBAction)clearPressed:(UIButton *)sender;
- (IBAction)enterPressed:(UIButton *)sender;
- (IBAction)octopusPressed:(UIButton *)sender;
- (IBAction)signPressed:(UIButton *)sender;
- (IBAction)add:(UIButton *)sender;
#end
Thanks to any and all help. This site is really the best!!
When your textFieldShouldBeginEditing: method is called, the first responder has not been set to the correct field yet. Replace the textFieldShouldBeginEditing: with textFieldDidBeginEditing: to fix this problem.