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
Related
There are few answers on SO (UILongPressGestureRecognizer), but I'm unable to get the correct value with the following code, not sure what I'm doing wrong. Tried few more pages on SO and similar one more third party website tutorial but unable to get the exact button detail.
#property (nonatomic,strong) UILongPressGestureRecognizer *lpgr;
#property (strong, nonatomic) IBOutlet UIButton *button1;
#property (strong, nonatomic) IBOutlet UIButton *button2;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPressGestures:)];
self.lpgr.minimumPressDuration = 2.0f;
self.lpgr.allowableMovement = 100.0f;
[self.view addGestureRecognizer:self.lpgr];
}
- (void)handleLongPressGestures:(UILongPressGestureRecognizer *)gesture
{
if ([gesture isEqual:self.lpgr]) {
if (gesture.state == UIGestureRecognizerStateBegan)
{
if (gesture.view == self.button1) {
NSLog(#"Button 1 is pressed for long");
}else if(gesture.view == self.button2) {
NSLog(#"Button 2 is pressed for long");
}else{
NSLog(#"another UI element is pressed for long");
}
}
}
}
Every time button is press for long, I'm getting NSLog(#"another UI element is pressed for long");
The else statement is being hit every time because you are adding the gesture to the main view. Even when you are long pressing on the button the event is being passed up to the view where you are catching it. If you add the lines below in viewDidLoad it will fire on the buttons appropriately.
[self.button1 addGestureRecognizer:self.lpgr];
[self.button2 addGestureRecognizer:self.lpgr];
You have added gestures to self.view instead of button1/button2.
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.
I have a programatically created UITextField added to the NavigationController as below (within a UITableViewController since I wanted a custom fixed search bar at the top).
In .h file
#property (nonatomic, strong) UITextField *searchText;
In .m file
#synthesize searchText;
self.searchText = [[UITextField alloc] init];
self.searchText.frame = CGRectMake(35, 234, 250, 27);
self.searchText.backgroundColor = Rgb2UIColor(255, 255, 255);
[self.navigationController.view addSubview:self.searchText];
self.searchText.delegate = self;
However none of the following methods get triggered
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
}
-(void)textFieldDidBeginEditing:(UITextField *)textField{
self.searchText.returnKeyType = UIReturnKeySearch;
}
- (void)textFieldDidEndEditing:(UITextField *)textField{
}
Can someone point me to the right direction on why my delegate does not work?
Better use uiseachbar from the objects panel. This comes with default search bar style and effects but is similar to uitextfield. You can set the delegate and listen to it the same way as you do for textview.
I am creating UIViewController programmatically. In its viewDidLoad, I am creating instance of custom UIView Component which has bunch of button and text filed. I set this view as viewControllers view.
But when I select any UIButton it does not fire any event or tapping inside UITextFiled does not bring up keyboard either.
- (void)viewDidLoad
{
[super viewDidLoad];
SomeView *sv = [[SomeView alloc] initWithFrame:self.view.bounds];
self.view.userInteractionEnabled = YES;
self.view = sv;
//[self.view addSubView:sv];
self.title = #"Something";
}
Is there anything wrong with this piece of code ? Even adding subivew does not work.
I added tapgesture to sv and It was getting detected but nothing else was getting selected on view.
I tried added buttons/textfiled to the viewcontrollers view directly. Then it works but not through customview component.
Try holding a strong reference to the view, It might be getting deallocated.
#interface YOURCLASS ()
#property (nonatomic, strong) SomeView *sv;
#end
And then Go back fro trying to add it as a subview. See if that works.
- (void)viewDidLoad
{
[super viewDidLoad];
self.sv = [[SomeView alloc] initWithFrame:self.view.bounds];
self.view.userInteractionEnabled = YES;
[self.view addSubView:self.sv];
self.title = #"Something";
}
i have my button, created from storyboard:
#property (weak, nonatomic) IBOutlet UIButton *plusOneBtnPoisonTwo;
with its method:
- (IBAction)plusOnePlayerTwoPoison:(id)sender;
then I check device rotation and set new position:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
// NSLog(#"%d", toInterfaceOrientation);
if(!UIInterfaceOrientationIsPortrait(toInterfaceOrientation)){
self.plusOneBtnPoisonTwo.center = CGPointMake(284, 406);
}
}
the button moves in the new position, but the method plusOnePlayerTwoPoison is no more triggered...
Any Idea?
Thanks.
Try using this instead. Its just a guess that it may resolve your problem.
#property (retain, nonatomic) IBOutlet UIButton *plusOneBtnPoisonTwo; //change to retain
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//add button action manually by code
[plusOneBtnPoisonTwo addTarget:self action:#selector(plusOnePlayerTwoPoison:) forControlEvents:UIControlEventTouchDown];
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
// NSLog(#"%d", toInterfaceOrientation);
if(!UIInterfaceOrientationIsPortrait(toInterfaceOrientation)){
[plusOneBtnPoisonTwo setFrame:CGRectMake(284, 406,50,100)];
}
}