If the user keeps clicking on button1 one or two , progress2.progress keeps increasing/decreasing on each click and progress1.progress keeps the same value until the user stops clicking. And in case he will surely lose , if he also keeps clicking nothing happens until he stops clicking. I don't want it to be that way since I want to hide/disable the buttons as soon as it's confirmed that he's losing to fix this issue. Any way to fix that?
Here is my .m :
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (BOOL)prefersStatusBarHidden { return YES; }
- (void)viewDidLoad
{
progress1.progress=arc4random() % 11 * 0.1;
count1=0;
count2=0;
label1.hidden = NO;
gameOver.hidden = YES;
score=0;
[super viewDidLoad];
;
}
// Do any additional setup after loading the view, typically from a nib.
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)regulator{
if(timer1)
{
[timer1 invalidate];
timer1 = nil;
}
if(timer4)
{
[timer4 invalidate];
timer4 = nil;
}
timer4 =[NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:#selector(conditioner) userInfo:nil repeats:YES];
;}
-(void)conditioner {
if (fabs(progress2.progress-progress1.progress)<=0.25 )
{
score=score+1;
scorenumber.text= [NSString stringWithFormat:#"%i",score];
[self newGame];
;
} else{
stop1=YES;
stop2=YES;
gameOver.hidden=NO;
stick.hidden=YES;
bg.hidden=YES;
progress1.hidden=YES;
progress2.hidden=YES;
supply.hidden=YES;
demand.hidden=YES;
}}
-(void)newGame{
progress1.progress=arc4random() % 11 * 0.1;}
- (IBAction)start:(UIButton *)sender {
progress2.progress=arc4random() % 11 * 0.1;
if(timer4)
{
[timer4 invalidate];
timer4 = nil;
timer1 = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(regulator) userInfo:nil repeats:YES];
[self regulator];
stop1=NO;
stop2=NO;
label1.hidden=YES;
UIButton *button1 = (UIButton *)sender;
button1.enabled = NO;
UIButton *button2 = (UIButton *)sender;
button2.enabled = NO;
}
- (IBAction)button1:(UIButton *)sender {
if(stop1==YES){button12.hidden = TRUE;}
progress2.progress=progress2.progress-0.05;
;
[self regulator];
count2=0;
count1 = count1 +1;
}
- (IBAction)button2:(UIButton *)sender {
[self regulator];
progress2.progress=progress2.progress+0.05;
if(stop2==YES){button22.hidden = TRUE;}
count1 =0;
count2 = count2+1;
}
#end
and my .h:
#import <UIKit/UIKit.h>
int count1;
int count2;
int score;
void *regulator;
void *newGame;
void *conditioner;
BOOL stop1;
BOOL stop2;
void *firstLaunch;
#interface ViewController : UIViewController{
IBOutlet UILabel *scorenumber;
IBOutlet UIImageView *stick;
IBOutlet UILabel *label1;
IBOutlet UIImageView *bg;
IBOutlet UILabel *supply;
IBOutlet UILabel *demand;
IBOutlet UILabel *gameOver;
IBOutlet UIProgressView *progress1;
IBOutlet UIProgressView *progress2;
IBOutlet UIButton *button12;
IBOutlet UIButton *button22;
NSTimer *timer1;
NSTimer *timer2;
NSTimer *timer3;
NSTimer *timer4;
}
- (IBAction)button1:(UIButton *)sender;
- (IBAction)button2:(UIButton *)sender;
#end
Thanks a lot for any help or information. I edited my question with the full code to give further explanation about the issue I'm facing. Regards.
This is actually a coding issue. MVC basics.
I believe you miss some understanding of things. So I'll explain:
IBAction - It's an action sent from the view to the controller.
IBOutlet - Meant for the controller to control the view.
On your code you are getting the sender (which should be read only when coding right) and you are trying to set it up. I assume you need to define a new IBOutlet to represent the button then connect it on your storyboard and then inside this function to make it enable/disabled.
Also a good practice would be to use "TRUE" and "FALSE" and not "YES/NO".
Hope this helps.
There are couple of ways you can approach this to make sure when user touches the button then it doesn't do anything.
It wasn't clear from your question so I assume on touch down of button you call (IBAction)button1. So Try
- (IBAction)button1:(UIButton *)sender
{
if(stop1==YES)
{
//game has stopped so don't do anything
}
else
{
progress2.progress=progress2.progress-0.05;
[self regulator];
}
}
If you want to hide it so that the user can't do anything try this
- (IBAction)button1:(UIButton *)sender
{
if(stop1==YES)
{
//game has stopped so hide this button
//assuming you have connected an IBOutlet to your button1
button1.hidden = YES;
}
else
{
button1.hidden = NO;
progress2.progress=progress2.progress-0.05;
[self regulator];
}
}
Related
I'm using Objective-C to make a stopwatch. I already have a basic stop watch with 3 buttons: Start, Stop and reset. Here is my code for viewcontroller.m:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
-(IBAction)Start:(id)start
{
Timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(addingthetime) userInfo:nil repeats:YES];
}
-(IBAction)Stop:(id)sender
{
[Timer invalidate];
}
-(IBAction)Restart:(id)sender
{
[Timer invalidate];
addingtheTime = 0;
Label.text = [NSString stringWithFormat:#"0.00"];
}
-(void)addingthetime
{
addingtheTime = addingtheTime + 0.01;
Label.text = [NSString stringWithFormat:#"%.2f", addingtheTime];
}
#end
And here is my code for viewcontroller.h:
#import <UIKit/UIKit.h>
float addingtheTime;
#interface ViewController : UIViewController
{
IBOutlet UILabel *Label;
NSTimer *Timer;
}
#end
So my question is how do I make the Start button do the following once clicked:
Start the timer
Change the title to stop
(Click the same button again)
Stop the timer
Change the title to start
So the aim is to have only one button which starts and stops the timer but please I want the title to change as well.
Don't worry about the reset button as I want that to remain by itself.
PS. Please explain things clearly because I find it really hard to understand some things and I am a beginner so try and keep it fairly simple thanks, and sorry if the question isn't clear.
You can use button.tag property to achieve this. By Default the button.tag property have 0. So assume that 0 is a state when timer is Not started and 1 is the state when timer is started. You can manipulate .tag property according to your custom logic.
-(IBAction)Start:(id)start
{
UIButton *button = (UIButton *)start;
if (button.tag == 0){
button.tag = 1;
[button setTitle:#"Stop" forControlState:UIControlStateNormal];
Timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(addingthetime) userInfo:nil repeats:YES];
}else {
button.tag = 0;
[button setTitle:#"Stop" forControlState:UIControlStateNormal];
//Invoke your method to stop Timer.
}
}
In the ViewController.h:
#import <UIKit/UIKit.h>
float addingtheTime;
#interface ViewController : UIViewController
{
IBOutlet UILabel *Label;
NSTimer *Timer;
}
#end
In the ViewController.m:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)addingthetime
{
addingtheTime = addingtheTime + 0.01;
Label.text = [NSString stringWithFormat:#"%.2f", addingtheTime];
}
- (IBAction)startOrStopAction:(UIButton *)sender {
// stop
if ([sender.titleLabel.text isEqualToString:#"stop"]) {
[Timer setFireDate:[NSDate distantFuture]];
[sender setTitle:#"start" forState:UIControlStateNormal];
}
// start
else {
if (!Timer) {
Timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(addingthetime) userInfo:nil repeats:YES];
}else {
[Timer setFireDate:[NSDate date]];
}
[sender setTitle:#"stop" forState:UIControlStateNormal];
}
}
#end
The result:
In iPhone:
In iPad:
I'm a beginner to Xcode nd Objective-C! I'm making an ios app which is basically a stop watch. The idea is only to have two buttons. One to reset the stopwatch and the other to start and stop the clock. (Basically, you click the start button which then turns into a stop button which when clicked will stop the stopwatch. The problem is I have two errors which are the same and read the following: (I don't know how to fix them which is the question!)
No visible #interface fro 'UIButton' declares the selector 'setTitle:forControlState:'
This has come up twice at two points! Point one:
[button setTitle:#"Start" forControlState:UIControlStateNormal];
And point two...
[button setTitle:#"Stop" forControlState:UIControlStateNormal];
Here is my code for VeiwController.h:
//
#import <UIKit/UIKit.h>
float addingtheTime;
#interface ViewController : UIViewController
{
IBOutlet UILabel *Label;
NSTimer *Timer;
}
#end
Here is my code for ViewController.m
//
#import "ViewController.h"
#interface ViewController ()\
#end
#implementation ViewController
-(IBAction)Start:(id)start
{
UIButton *button = (UIButton *)start;
if (button.tag == 0){
button.tag = 1;
[button setTitle:#"Start" forControlState:UIControlStateNormal];
Timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(addingthetime) userInfo:nil repeats:YES];
}else {
button.tag = 0;
[button setTitle:#"Stop" forControlState:UIControlStateNormal];
//Invoke your method to stop Timer.
}
}
-(IBAction)Restart:(id)sender
{
[Timer invalidate];
addingtheTime = 0;
Label.text = [NSString stringWithFormat:#"0.00"];
}
-(void)addingthetime
{
addingtheTime = addingtheTime + 0.01;
Label.text = [NSString stringWithFormat:#"%.2f", addingtheTime];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Please note I am a beginner so please explain as much as you can and thanks you in advance for any help!!!
its forstate not forControlState
[button setTitle:#"start" forState:UIControlStateNormal];
[button setTitle:#"stop" forState:UIControlStateNormal];
Xcode 5 / iOS 7.
This problem has been driving me crazy for the better part of a day now. In my current project, I'm unable to hide the iOS keyboard using resignFirstResponder. However, strangely, I am able to get this to work in all other projects I'm currently working on. Code below. Thanks so much, guys!
ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITextFieldDelegate>
{
IBOutlet UISegmentedControl *selectcontrolNumbers;
IBOutlet UILabel *output;
int grossNetVar;
double calcVariable;
IBOutlet UIButton *hideConvertNet;
IBOutlet UIButton *hideConvertGross;
}
#property (strong, nonatomic) IBOutlet UITextField *dollarTextField;
#property (nonatomic)int grossNetVar;
#property (nonatomic) double calcVariable;
- (IBAction)selectAction:(id)sender;
- (IBAction)convertToNet:(id)sender;
- (IBAction)convertToGross:(id)sender;
#end
ViewController.m:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize grossNetVar;
#synthesize calcVariable;
- (void)viewDidLoad
{
[super viewDidLoad];
self.dollarTextField.delegate = self;
}
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.dollarTextField resignFirstResponder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)selectAction:(id)sender {
if (selectcontrolNumbers.selectedSegmentIndex == 0){
grossNetVar = 1;
} else {
grossNetVar = 2;
}
if (grossNetVar == 1) {
hideConvertGross.enabled = YES;
hideConvertNet.enabled = NO;
} else {
hideConvertGross.enabled = NO;
hideConvertNet.enabled = YES;
}
}
- (IBAction)convertToNet:(id)sender {
NSString *textFieldText = _dollarTextField.text;
calcVariable = .85;
double dollarTotal = [textFieldText doubleValue];
double netCalc = calcVariable * dollarTotal;
NSString *netString = [[NSString alloc]initWithFormat:#"The NET total is %g", netCalc];
output.text = netString;
}
- (IBAction)convertToGross:(id)sender {
}
#end
I would recommend using a toolbar (you can drag one on to the screen into the storyboard) that only appears when the keyboard is opened, and put a done button on that. Create an IBAction for the touchdown of that button in which you can do
[donebutton resignFirstResponder];
I am writing a simple application that consists of 2 UIImageViews and 2 UIButtons. The UIImageViews are placed on top of the UIButtons.
I have 1 UIImage that appears on a random UIImageView and disappears after 2 seconds. The user then has to tap on the button they think the image appeared on.
I shuffle the UIImageView array and use the first element (index 0) for the image to be displayed on. When shuffling I keep track of which element (i.e from which index. lets say from index "n") was placed on index 0 of the array.
However, when a button is pressed i compare the id of the button pressed with the id of the button with index n. (because that is the index of the random UIImageView).
But for some reason it is not working. :(
Here is my code: (i didn't upload the .h file. it just contains declarations.)
The code below doesn't produce any error/warning messages. It just doesn't output the result I want.
#interface ViewController ()
#property (strong, nonatomic) NSMutableArray* tempButton;
#property (strong, nonatomic) NSMutableArray *tempViews;
#property (strong, nonatomic) UIImage *myImage;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_myImage = [UIImage imageNamed:#"hello"];
_tempButton = [[NSMutableArray alloc] initWithObjects:_button1, _button2, nil];
_tempViews = [[NSMutableArray alloc]initWithObjects:_image1, _image2, nil];
[self displayonView];
}
-(void)displayToFindSymbol{
[_toFindImage setImage:_myImage];
_toFindImage.contentMode = UIViewContentModeScaleAspectFit;
}
- (IBAction)pressed:(id)sender {
UIButton *result = (UIButton *)sender;
if (result == _tempButton[_correctButton]) {
NSLog (#"Correct");
}
else if (result != _tempButton[_correctButton]){
NSLog (#"Incorrect");
}
}
-(NSMutableArray *)shuffleViews{
NSUInteger count = _tempViews.count;
int n;
for (int i=count-1; i>=0; --i) {
n = arc4random() % (i + 1);
[_tempViews exchangeObjectAtIndex:n withObjectAtIndex:i];
}
_correctButton = n;
return _tempViews;
}
-(void)displayonView{
NSMutableArray *tempArray;
tempArray = [self shuffleViews]; // shuffle views
_correctImage = [tempArray objectAtIndex:0];
_correctImage.contentMode = UIViewContentModeScaleAspectFit;
[_correctImage setImage:_myImage];
NSTimer* myTImer;
myTImer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(hideLabel) userInfo:nil repeats:NO];
}
-(void) hideLabel{
_correctImage.hidden = YES;
for (UIButton *each in self.tempButton) {
each.enabled = YES;
}
[self displayToFindSymbol];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
Use tags instead, set a unique tag to both of the buttons, and set the tag of image to the button that the image will belong, later on, compare the tag of both image and the button to check if they are the same or not.
https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/UIView/UIView.html#//apple_ref/occ/instp/UIView/tag
I'm kinda new to objective-c and iOS aswell, but i don't think you should compare like this:
result == _tempButton[_correctButton]
try this comparison instead:
[result isEqual:_tempButton[_correctButton]]
I want to have a certain method run and repeat itself for as long as someones finger is pressed down on a button. I want that method to stop repeating itself when the finger is not on the button anymore
Is there a way to check if the touchDown is still occurring during the method implementation? Help!
You can use the UIControlEventTouchDown control event to start the method running, and UIControlEventTouchUpInside, or similar, to detect when the button is no longer being "pressed".
Set up the actions to the button, e.g.:
[myButton addTarget:self action:#selector(startButtonTouch:) forControlEvents:UIControlEventTouchDown];
[myButton addTarget:self action:#selector(endButtonTouch:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
(Note the above will cause touch up inside and outside the button to invoke the endButtonTouch: method.)
Then add the startButtonTouch: and endButtonTouch methods, e.g., :
- (void)startButtonTouch:(id)sender {
// start the process running...
}
- (void)endButtonTouch:(id)sender {
// stop the running process...
}
Drawing upon the bobnoble's answer here's a helper view
#import <UIKit/UIKit.h>
#interface YOIDCAutorepeatingButton : UIButton
// you COULD pinch pennies switching to nonatomic, but consider
// how much time it would take to debug if some day some moron decides without checking this spec
// to alter this prop off another thread
#property (atomic) NSTimeInterval delayUntilAutorepeatBegins;
#property NSTimeInterval delayBetweenPresses;
#property (weak) id<NSObject> recipient;
#property SEL touchActionOnRecipient;
#end
-------------> .m
#import "YOIDCAutorepeatingButton.h"
#interface YOIDCAutorepeatingButton()
{
NSTimeInterval _pressStartedAt;
}
#end
#implementation YOIDCAutorepeatingButton
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self addTarget:self action:#selector(startButtonTouch:) forControlEvents:UIControlEventTouchDown];
[self addTarget:self action:#selector(endButtonTouch:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
self.delayUntilAutorepeatBegins = .250;
self.delayBetweenPresses = .080;
}
return self;
}
-(void)killLastCharacter:(id)sender
{
[self.recipient performSelector:self.touchActionOnRecipient withObject:sender];
}
- (void)performAutorepeat:(id)sender
{
if(!self.delayBetweenPresses) {
// bail
return;
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.delayBetweenPresses * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if(_pressStartedAt) {
[self killLastCharacter:sender];
[self performAutorepeat:sender];
}
});
}
- (void)startButtonTouch:(id)sender {
[self killLastCharacter:sender];
NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
_pressStartedAt = now;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.delayUntilAutorepeatBegins * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if(_pressStartedAt) {
[self killLastCharacter:sender];
[self performAutorepeat:sender];
}
});
}
- (void)endButtonTouch:(id)sender {
_pressStartedAt = 0;
}
#end
-------- sample usage -------
- (IBAction)killLastDigit:(id)sender {
.....
- (void)viewDidLoad
{
assert(self.backSpace);
[YOIDCAutorepeatingButton class]; // if xib is in a bundle other than main gottal load the class
// otherwise you'd get -[UIButton setRecipient:]: unrecognized selector sent to instance
// on setRecipient:
self.backSpace.recipient = self;
self.backSpace.touchActionOnRecipient = #selector(killLastDigit:);