IOS: UILongPressGestureRecognizer EXC_BAD_ACCESS - ios

I have this code in viewDidLoad:
UILongPressGestureRecognizer *change = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(dragGestureChange:)];
[imageView addGestureRecognizer:change];
for (UILongPressGestureRecognizer *gestureRecognizer in imageView.gestureRecognizers)
{
[gestureRecognizer requireGestureRecognizerToFail:change];
}
when I call the class where is this code, the first time it's all ok , but the second time it crash because EXC_BAD_ACCESS; it don't happens if instead of an imageView I use a scrollView, why???

With this code, you are requiring all recognizers (including change) to fail for change to succeed, which cannot be good
UILongPressGestureRecognizer *change = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(dragGestureChange:)];
[imageView addGestureRecognizer:change];
for (UILongPressGestureRecognizer *gestureRecognizer in imageView.gestureRecognizers)
{
[gestureRecognizer requireGestureRecognizerToFail:change];
}
you should change it to this
UILongPressGestureRecognizer *change = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(dragGestureChange:)];
for (UILongPressGestureRecognizer *gestureRecognizer in imageView.gestureRecognizers)
{
[gestureRecognizer requireGestureRecognizerToFail:change];
}
[imageView addGestureRecognizer:change];
And you should release change here. Don't know if that will actually solve your problem, can't see anything else wrong in what you posted.

Maybe try this: UIButtonLongTab. Use the Background-Image for your Images. I use this in an App within a ScrollView and it works without problem.

Related

how can check that which uiimageview is presently clicked?

I have three UIImageview. I set the action for UIImageview by using tapGesture. I want each UIImageview to have a different action. How can I check that which UIImageview is presently clicked?
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapping:)];
[singleTap setNumberOfTapsRequired:1];
[_imageOne addGestureRecognizer:singleTap];
[_imageTwo addGestureRecognizer:singleTap];
[_imageThree addGestureRecognizer:singleTap];
-(void)singleTapping:(UIGestureRecognizer *)recognizer {
}
You can detect using below code:
-(void)singleTapping:(UITapGestureRecognizer *) recognizer{
if (recognizer.view == _imageOne){
} else if (recognizer.view == _imageTwo) {
}else
{
}
}
A UIGestureRecognizer is to be used with a single view. There is this explicit information in the Apple documentation:
Gesture Recognizers Are Attached to a View
Every gesture recognizer is associated with one view. By contrast, a
view can have multiple gesture recognizers, because a single view
might respond to many different gestures. For a gesture recognizer to
recognize touches that occur in a particular view, you must attach the
gesture recognizer to that view.
Firstly, you can't attach same UITapGestureRecognizer to more than one view.
So, your code will not work and you have to create three UITapGestureRecognizer instances and have to attach it to views like below:
UITapGestureRecognizer *singleTapImg1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapping:)];
[singleTapImg1 setNumberOfTapsRequired:1];
UITapGestureRecognizer *singleTapImg2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapping:)];
[singleTapImg2 setNumberOfTapsRequired:1];
UITapGestureRecognizer *singleTapImg3 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapping:)];
[singleTapImg3 setNumberOfTapsRequired:1];
[_imageOne addGestureRecognizer:singleTapImg1];
[_imageTwo addGestureRecognizer:singleTapImg2];
[_imageThree addGestureRecognizer:singleTapImg3];
Now, you can use below code to get, which imageview clicked and perform action according to that:
-(void)singleTapping:(UIGestureRecognizer *)recognizer {
if (recognizer.view == _imageOne){
//_imageOne tapped
}
else if (recognizer.view == _imageTwo) {
//_imageTwo tapped
}else{
//_imageThree tapped
}
}

How to get tag from UIImageViiew in ios?

I have added tap gesture on UIImageView. I want to get the tag from it when I tap on the image. Please tell me how can I do it?
UITapGestureRecognizer *tapGesture1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tap_post_image:)];
tapGesture1.numberOfTapsRequired = 1
[tapGesture1 setDelegate:self];
[cell.beizer_image setUserInteractionEnabled:true];
[cell.beizer_image addGestureRecognizer:tapGesture1];
[cell.beizer_image setTag:indexPath.row];
- (void) tap_post_image: (id)sender
{
NSInteger the_tag = ((UIView*)sender).tag;
NSLog(#"tap post image is called");
NSLog(#"TAG is %ld",(long)the_tag);
}
Above code crashes the app.
While you really need to provide details of the crash on your question, one obvious issue is that you assume the sender parameter of your top_post_image: method is a UIView.
This is incorrect. The parameter will be the gesture recognizer, not a view. But you can get the view from the gesture.
The code should be:
- (void)tap_post_image:(UITapGestureRecognizer *)gesture {
NSInteger the_tag = gesture.view.tag;
}
On an unrelated note you need to work on your naming conventions. In Objective-C (as well as many other languages), it is common practice to use what is called "camel case'. Your method should be named tapPostImage:, not tap_post_image.
You will crash because sender in your code is not uiview, uiimageview.
sender is UITapGestureRecognizer class.
You should do
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapImageView:)];
[tapGesture setNumberOfTapsRequired:1];
[self.sampleImage setUserInteractionEnabled:YES];
[self.sampleImage addGestureRecognizer:tapGesture];
[self.sampleImage setTag:99];
- (void)tapImageView:(id)sender {
NSLog(#"Sender is a %# class",NSStringFromClass([sender class]));
UITapGestureRecognizer *tapGesture = ((UITapGestureRecognizer *)sender);
UIImageView *imageView = (UIImageView *)tapGesture.view;
NSLog(#"imageView.tag = %d",imageView.tag);
}
I hope it helps!

UILongPressGestureRecognizer on UISwitch does not fire

Today I tried to add an additional UILongPressGestureRecognizer to an UISwitch, which did not really work. My code is the following:
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(doSomething:)];
[lpgr setDelaysTouchesBegan:YES];
[lpgr setDelaysTouchesEnded:YES];
[lpgr setCancelsTouchesInView:YES];
[self.switcher addGestureRecognizer:lpgr];
in the viewDidLoad method of the viewController that is the parent viewController of that switch. (the switcher is an instance variable, set through a storyboard. The IBOutlet is set properly from the UISwitch to the switcherProperty of its viewController).
On a couple of other controls (like a UIButton, UISlider, UIStepper and so on) this works, even without the touches cancelled or delayed, and perfectly triggers the target method. However, with my switch, it refuses that behavior.
I have tried removing any other gestureRecognizer on the UISwitch by iterating through all gestureRecognizers on that switch and calling [switcher removeGestureRecognizer: ... ], I´ve also set all of them to require my longPressGestureRecognizer to fail. Other types of gestureRecognizers don´t fire as well.
As far as I understand, GestureRecognizers will receive touches, before the view or control, which they belong to, receives them. Thus, setCancelsTouchesInView:YES and setDelaysTouchesInView:YES should enable the gestureRecognizer to handle every single gesture until it fails or succeeds, without the view knowing, right?
--------------EDIT------------------
The whole content of my method:
- (void)viewDidLoad
{
[super viewDidLoad];
UIGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(edit:)];
[self.view addGestureRecognizer:lpgr];
lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(edit:)];
[self.button addGestureRecognizer:lpgr];
lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(edit:)];
[self.slider addGestureRecognizer:lpgr];
lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(edit:)];
[self.segmentedControl addGestureRecognizer:lpgr];
lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(edit:)];
[self.switcher addGestureRecognizer:lpgr];
lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(edit:)];
[self.stepper addGestureRecognizer:lpgr];
}
As I said, for the other controls this is working, only the switch does not want to work
try with it
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// Disallow recognition of tap gestures in the segmented control.
if ((touch.view == yourSwitch)) {//change it to your condition
return NO;
}
return YES;
}
make sure you confirm UIGestureRecognizerDelegate for it to work.

iOS - TapGestureRecognizer - Tap is applicable for the whole screen not for a view

In my app, I have an image and a UITextView.
I have created a UITapGestureRecognizer for both the views but the issue is that wherever I click on the screen, only the method associated with the UITextView gets executed.
Even if I click on the image, only the UITapGestureRecognizer method associated with the UITextView gets executed.
Following is the code I've implemented:
UITapGestureRecognizer *tapGestureRecognizerImage = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleTapFromImage:)];
[infobutton addGestureRecognizer:tapGestureRecognizerImage];
[[self view] addGestureRecognizer:tapGestureRecognizerImage];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleTapFrom:)];
[messageOne addGestureRecognizer:tapGestureRecognizer];
[[self view] addGestureRecognizer:tapGestureRecognizer];
//The following are the methods associated
- (void) handleTapFrom: (UITapGestureRecognizer *)recognizer {
//Code to handle the gesture
NSLog(#"I am in handleTapFrom method");
}
- (void) handleTapFromImage: (UITapGestureRecognizer *)recognizer {
//Code to handle the gesture
NSLog(#"I am in handleTapFrom Image method");
[self.view makeToast:#"Your verification code does not match. Re-enter your verification code"];
}
I am sure I am missing something here.
The association in storyboard is correct to my knowledge.
Please correct me where I am going wrong
Thanks for your time
You should not add gesture on self.view.
It should get added on the view for which you want to identify tap event.
You are setting both the Tap Gesture Objects on [self view] object.
Also, the UIImageView object, lets call it imageObj, should have userInteractionEnabled = YES.
instead of:
[[self view] addGestureRecognizer:tapGestureRecognizerImage];
you should do:
[imageObj setUserInteractionEnabled:YES];
[imageObj addGestureRecognizer:tapGestureRecognizerImage];
You generally use -addGestureRecognizer: on the object you want your gesture object to work on.
Say you have a UITapGestureRecognizer object called myTapGesture.
Then, to make it work...
on a UILabel *lblSomeObj it will be:
[lblSomeObj addGestureRecognizer:myTapGesture];
on a UIView *vwSomeObj it will be:
[vwSomeObj addGestureRecognizer:myTapGesture];
etc...
Just add the gesture in the respective views and not in self.view.
UITapGestureRecognizer *tapGestureRecognizerImage = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapFromImage:)];
[infobutton addGestureRecognizer:tapGestureRecognizerImage];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapFrom:)];
[messageOne addGestureRecognizer:tapGestureRecognizer];
Add gesture on UIImageView object and make sure that image view userInteractionEnabled is set to YES
imageObj.userInteractionEnabled = YES;
[imageObj addGestureRecognizer:tapGestureRecognizerImage];
You need to include this piece of code:-
[tapGestureRecognizerImage requireGestureRecognizerToFail:tapGestureRecognizer];
[imageObj addGestureRecognizer:tapGestureRecognizerImage];

Is it possible to add two gestures in a view?

As the title of this question said, I need to create a view where it needs to have action when one tap it or hold it. That means I have to add UITapGestureRecognizer and a UILongPressGestureRecognizer. I have already tried it. Somehow it redirect me to the screen where I needed to go, but it has affected it's back button. Affected by in the sense of it goes back to default text which is "Item" and it cannot perform it's assigned action.
Yes you can add these two gestures in one view. See the below code
UITapGestureRecognizer *singleTapRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(didTap:)];
singleTapRecognizer.numberOfTapsRequired = 1;
singleTapRecognizer.delegate = self;
[self.view addGestureRecognizer:singleTapRecognizer];
UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:#selector(didLongPress:)];
[longPressRecognizer setDelegate:self];
longPressRecognizer.allowableMovement = 1.0f;
longPressRecognizer.minimumPressDuration = 2.0;
[self.view addGestureRecognizer:longPressRecognizer];
As i mentioned in my comment you can do so,here is some piece of code to help you out.
UITapGestureRecognizer * recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
recognizer.delegate = self;
[view addGestureRecognizer:recognizer];
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleLongPress:)];
longPress.minimumPressDuration = 2.0;
[view addGestureRecognizer:longPress];
and here are are some links too for your better understanding:-
https://developer.apple.com/library/ios/documentation/uikit/reference/UILongPressGestureRecognizer_Class/Reference/Reference.html
https://developer.apple.com/library/ios/documentation/uikit/reference/UITapGestureRecognizer_Class/Reference/Reference.html
Hope this will help you out.

Resources