Disabling all buttons until an IBAction completed - ios

I have four buttons on a single view. Each button has a different IBaction. Once one is pressed I would like to lock out all buttons from being pressed again until the action is completed. I have tried to give each one a property in the .h and then under each IBAction in the .m, I have set each of the four buttons like this btnHelp.enabled =NO;,., etc and then at the end before the final } I have reenabled them all. This hasn't worked. I am a new to objective-C and xcode and greatly appreciate any help.
This is IOS. The .h code is :
#property (strong, nonatomic) IBOutlet UIButton *btnHelp;
#property (strong, nonatomic) IBOutlet UIButton *btnSpin;
#property (strong, nonatomic) IBOutlet UIButton *btnScore;
#property (strong, nonatomic) IBOutlet UIButton *btnBet;
- (IBAction)slotHelp:(id)sender;
- (IBAction)slotSpin:(id)sender;
- (IBAction)slotBet:(id)sender;
- (IBAction)slotScore:(id)sender;
The .m is :
#synthesize btnHelp, btnScore, btnSpin, btnBet;
- (void)viewDidLoad
{
[super viewDidLoad];
btnHelp.enabled = NO;
btnBet.enabled = NO;
btnScore.enabled = NO;
btnSpin.enabled = NO;
// do some introductory setup and give some spoken instructions
// Load plist data into array, etc
// Then reenable buttons
btnHelp.enabled=YES;
btnBet.enabled=YES;
btnScore.enabled=YES;
btnSpin.enabled=YES;
}
-(IBAction)slotHelp {
// Disable buttons while we complete action
btnHelp.enabled = NO;
btnBet.enabled = NO;
btnScore.enabled = NO;
btnSpin.enabled = NO;
// stuff to do
// Reenable buttons after action event completed
btnHelp.enabled=YES;
btnBet.enabled=YES;
btnScore.enabled=YES;
btnSpin.enabled=YES;
}
There are three other action events for the other three buttons.
What I was trying to do is prevent accidental button presses during and action execution. I was hoping to have no chance of simultaneous button presses by accident. I am trying to make an app for use by physically challenged individuals who may accidentally press more than one button. I hope this helps explain a bit of why I want to block multiple presses even the same button.
Thanks for your interest and help.

As one of the most simple solution you may add a bool flag variable to your view class and add a check in you IBaction methods. Something like this
- (void)viewDidLoad
{
[super viewDidLoad];
lock = true;
// do some introductory setup and give some spoken instructions
// Load plist data into array, etc
// Then reenable buttons
lock = false;
}
-(IBAction)slotHelp {
if(!lock) {
lock = true;
//do what you need
lock = false;
}
and do the same check for all the other IBActions

As alternative way, you can globally block-unblock events with methods posted below, instead of blocking each button separately:
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
and
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
But be careful. Wrong strategy of using of these methods can block your application.

Related

How to make a toolbar which have TextView and show above Keyboard when Button Tapped

I know there are some questions about how to show a toolbar above keyboard.
I read some of them. But, I could not make the toolbar which have TextView like message app. I want to make a toolbar which is showed when button tapped.
I also use IB to create a toolbar because I need some adjustment to appearance.
The code now I make is below.
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UIToolbar *ibToolbar;
// this text view is subview of ibToolbar
#property (weak, nonatomic) IBOutlet UITextView *barTextView;
#end
- (void)viewDidLoad {
[super viewDidLoad];
[self.ibToolbar removeFromSuperview];
self.barTextView.inputAccessoryView = self.ibToolbar;
}
- (IBAction)buttonPushed:(id)sender {
[self.barTextView becomeFirstResponder];
}
When I tap the button, I want to look at toolbar above keyboard to put text on textView.
But, nothing happened when I push the button.
I think that why this code does not work, also because the viewController's view does not parent view of the toolbar,so [self.barTextView becomeFirstResponder] can not be effective.
I think that something else which I did is needed to work the things.
If anyone know do the things work, please tell me.

Error in if statement while comparing UITextField's text and a string

In my app, I have a view controller which is having a search bar with UItextfield at the top and a UIImageview below that. The image view is initially hidden.
I want this image view to unhide through an if statement. The user will enter keywords into the textfield and when a certain word will match a pre defined string in the.m file, then it must show the image.
I originally had two view controllers but now I added another one (thirdviewcontroller). As I enter a word into the textfield, the simulator will direct me back to the code highlighting in green on this line:
if ([string1 isEqualToString:string2]) {
locationMap.hidden = YES;
This is .h file:
#interface ThirdViewController : UIViewController
{
IBOutlet UITextField *searchLocation;
IBOutlet UIImageView *locationMap;
}
-(IBAction)SearchGo;
#end
This is the .m file:
-(IBAction)SearchGo{
NSString *string1 = searchLocation.text;
NSString *string2= #"sydney";
if ([string1 isEqualToString:string2]) {
locationMap.hidden = YES;
}
}
It sounds like you've accidentally set up a breakpoint. Simply remove the breakpoint by clicking the blue arrow to the left of the line it breaks on.
In viewDidLoad method, use:
locationMap.hidden = YES;
In your -(IBAction)SearchGo method, use:
locationMap.hidden = NO;
OR for your searchGo method:
-(IBAction)SearchGo{
if ([searchLocation.text isEqualToString:#"sydney"]) {
locationMap.hidden = NO;
}else {
//implementation
}
}
I am guessing, you have attached the IBAction with your textfield,searchLocation and triggered the action specifying "Touch up Inside". This will not work for couple of reasons.
First of all, you need to implement the textFieldShouldReturn: delegate method, so that your controller knows when you press return, it should hand over the control from your text field. Then again, a you have attached your action method to your text filed, as soon as you tap on the textfield, it goes to your method and start comparing but at this point, you have typed nothing in your textfield and it fails to conform to your if condition.
the solution is to either use the have a button and attach the action method to that button. That way, after you have typed the word "sydney", and you hit on the button. It will take whatever in your textfield and compare to that.
Here is the solution-
See the extra button named "Go". Attach your method to it.
This is my .h file-
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITextFieldDelegate>
#property(nonatomic, strong) IBOutlet UITextField *searchLocation;
#property(nonatomic, strong) IBOutlet UIImageView *locationMap;
-(IBAction)SearchGo:(id)sender;
#end
And this is the .m file-
#import "ViewController.h"
#interface ViewController ()
#property(nonatomic, strong) NSString *string1;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark- textfield delegate
- (void)textFieldDidEndEditing:(UITextField *)textField{
self.string1 = textField.text;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
-(IBAction)SearchGo:(id)sender{
NSString *string2= #"Sydney";
if ([self.string1 isEqualToString:string2]) {
self.locationMap.hidden = NO;
}
}
#end
Save the string from the textfield after your editing is done through the delegate method. Make sure, you attach the UITextFieldDelegate to your ViewController.
Alternatively, you may want to avoid all this trouble and use the UISearchDisplay controller.

UIButton enable doesn't work

I have a UIViewController with a single button and an activity indicator.
In the class for this VC MainViewController.m I do the following in viewDidAppear:
- (void)viewDidLoad
{
[super viewDidLoad];
_actLoadLoc.color = [UIColor blueColor];
_startButton.enabled = NO;
[_startButton setTitle:#"Fetching Location" forState:UIControlStateDisabled];
}
Another method in my MainViewController.m is called readyToGo and is implemented as follows:
-(void) readyToGo
{
[NSThread sleepForTimeInterval:1.0f];
NSLog(#"Done sleeping");
_startButton.enabled = YES;
[_startButton setTitle:#"Start" forState:UIControlStateNormal];
_actLoadLoc.stopAnimating;
}
I have properties for both UIButton, UIActivityIndicatorView and a declaration of the readyToGo method in my MainViewController.h as follows:
#property (weak, nonatomic) IBOutlet UIButton *startButton;
#property (weak, nonatomic) IBOutlet UIActivityIndicatorView *actLoadLoc;
-(void) readyToGo;
The readyToGo method is called from another class abc.[h/m] which imports MainViewController.h. The call happens after one of the functions in abc.m completes filling an array with calculated data.
The call works since Done Sleeping shows in the output, however the startButton is not enabled, its test does not change and the actLoadLoc does not stop animating... Any idea what's wrong with my code/method?
Thanks in Advance!
You are calling the readyToGo on the wrong instance of the view controller. You have an instance which is displaying content on the screen and you are, in some way, creating a new one to call the method on. You need to get the existing one instead.
It's not ideal, but you should be able to get the controller with:
UINavigationController *n = (UINavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
SDPPMainViewController *mvc = (SDPPMainViewController *)[n viewControllers][0];
(Will need to add some casts, and should probably break out to multiple lines)

Swipe left gestures over UITextField

I have UITextFields in tableviewcells. When you swipe over the cell not part of the textfield, the delete action comes up as expected. If you swipe over the textfield, it stops the delete from popping up.
How do I fix this so that you can swipe over the inputs and the cell will trigger the delete action?
I think the issue here is that the touch on the text field is interfering with your swipe gesture recognizer (presumably attached to the parent view). I had a similar problem with a text field that was placed in a UIScrollView.
I got around this problem by overlaying a clear UIView on top of my UITextField. I then assigned a UITapGestureRecognizer to this clear view to set the text field as the first responder when the user taps on the field. Otherwise, the swiped is sent to the parent view (a scroll view) which recognizes the swipe without any issues. It's kind of lame but it works.
This scenario is a bit different from yours, but I think it's the same problem. Here is what my code looks like, hopefully it helps:
// UIView subclass header
#interface LSAddPageView : UIView
#property (weak, nonatomic) IBOutlet UITextField *textField; // Connected to the UITextField in question
#property (strong, nonatomic) UIView *textFieldMask;
#property (assign, nonatomic) BOOL textFieldMaskEnabled;
#end
// UIView subclass implementation
#implementation LSAddPageView
- (void)awakeFromNib
{
[super awakeFromNib];
_textFieldMask = [UIView new];
_textFieldMask.backgroundColor = [UIColor clearColor];
[self insertSubview:_textFieldMask aboveSubview:self.textField];
}
- (void)layoutSubviews
{
[super layoutSubviews];
_textFieldMask.frame = self.textField.frame;
}
- (BOOL)textFieldMaskEnabled
{
return _textFieldMask.hidden == NO;
}
- (void)setTextFieldMaskEnabled:(BOOL)textFieldMaskEnabled
{
_textFieldMask.hidden = !textFieldMaskEnabled;
}
#end
And then in the controller:
- (void)viewDidLoad
{
[super viewDidLoad];
_addPageView = (LSAddPageView*)self.view;
_maskGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(didTapMask:)];
_maskGestureRecognizer.numberOfTapsRequired = 1;
_maskGestureRecognizer.numberOfTouchesRequired = 1;
[_addPageView.textFieldMask addGestureRecognizer:_maskGestureRecognizer];
self.textField.delegate = self; // Set delegate to be notified when text field resigns first responder
}
- (void)didTapMask:(UIGestureRecognizer*)recognizer
{
_addPageView.textFieldMaskEnabled = NO;
[self.textField becomeFirstResponder];
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
_addPageView.textFieldMaskEnabled = YES;
return YES;
}
Sounds like you need to set the cancelsTouchesInView property
yourGestureRecognizer.cancelsTouchesInView = NO;
from UIButton & UITextField will block UITableViewCell being swipe to delete
self.tableView.panGestureRecognizer.delaysTouchesBegan = YES;
this will make the textfield not stop left swipe guestures

Xcode hiding buttons

I'm curious to know is there a way to edit what happens at a app startup to hide buttons? I can hide them when the app is running but I want some buttons hidden when the app starts up and displayed later on after me touching one of my displayed buttons, is there a way to do this?
In code
UIView has a hidden property. You can toggle it to hide/show as you want in code, for example:
myView.hidden = YES; // YES/NO
You'll want to do this anywhere after -viewDidLoad
Interface Builder
In the inspector, once you've selected the view you want to hide, you should see something like this (look in the View > Drawing options - at the bottom).
It's the hidden property you want to check here... You'll want to make an outlet to your code so you can unhide this later on...
You could initially set your buttons hidden via the Attribute Inspector.
There's a check box down there View -> Drawing -> Hidden to hide the button.
Then you coud to set your buttons visible in the touch action of another visible button like following:
#import "HBOSViewController.h"
#interface HBOSViewController ()
// your buttons outlets here
#property (weak, nonatomic) IBOutlet UIButton *topButton1;
#property (weak, nonatomic) IBOutlet UIButton *topButton;
#end
#implementation HBOSViewController
- (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.
}
// The action of the visible button to make your hidden button visible.
- (IBAction)showButton:(id)sender {
if (self.topButton) {
self.topButton.hidden=NO;
}
if (self.topButton1) {
self.topButton1.hidden=NO;
}
}
#end
I assume you mean on a view which you created using a XIB (Interface Builder) file. If that's the case, simply set the hidden flag on any buttons you want to be initially hidden.
In -viewDidLoad just add something like yourButton.hidden = YES;

Resources