How to make my custom gesture recognizer class instances work simultaneously? - ios

You can download code example from this libk:
https://github.com/mriddi/ExempleCustomGestureRecognizer.git
I create my cusom gesture recognizer class like this:
#protocol MyGestureRecognizerDelegate <UIGestureRecognizerDelegate>
#optional
-(void) willDo;
#end
#interface MyGestureRecognizer: UIGestureRecognizer
{
…
}
#property (nonatomic, assign) id <MyGestureRecognizerDelegate> delegate;
…
#end
#implementation MyGestureRecognizer
#synthesize delegate;
…
-(void) call{
[delegate willDo];
}
…
#end
My ViewController adopt MyGestureRecognizerDelegate protocol.
In ViewController I create instances of my class:
MyGestureRecognizer * grFerst;
MyGestureRecognizer * grSecond;
grFerst.delegate=self;
grLeft.delegate=self;
[self.view addGestureRecognizer: grFerst];
[self.view addGestureRecognizer: grSecond];
I want to make both gesture recognizers instances to work simultaneously.
I try to add to my ViewController method
shouldRecognizeSimultaneouslyWithGestureRecognizer
but this method never calls, I checked it using NSLog function.
Please help me solve this problem (allow work both gesture recognizers simultaneously).

Maybe you should allocate the Gestures
MyGestureRecognizer * gesture = [[MyGestureRecognizer alloc] initWithTarget:self action:nil];
gesture.delegate = self;
[self.view addGestureRecognizer:gesture];
Or you could use the control wheel as the target and do all your angle calculations in there. Then you delegate back to the mainViewController.

Related

initWithTarget:self doesn't get my class to call selector

I create a class for dealing with dismissing keyboard
custom class:
tapReconizer.h:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface tapReconizer : NSObject {
UIView* myView;
}
-(void) tapreg:(UIView*)view;
#end
tapReconizer.m:
#import "tapReconizer.h"
#implementation tapReconizer
-(void) tapreg:(UIView*)view {
myView = view;
UITapGestureRecognizer *tapGestureRecognizer;
tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTap:)];
tapGestureRecognizer.numberOfTapsRequired = 1;
[myView addGestureRecognizer:tapGestureRecognizer];
}
- (void)singleTap:(UIGestureRecognizer *)recognizer {
[myView endEditing:true];
}
#end
and in my viewcontorller:
tapReconizer* reg = [[tapReconizer alloc]init];
[reg tapreg:self.view];
but it's seems singleTap: doesn't been called.
Can I do this all just in this custom class?
Thanks in advance.
Your tapReconizer instance (reg) gets deallocated when it goes out of scope at the end of whatever block it is created in.
You need to keep a strong reference to it. The easiest way is probably to make reg an instance variable.
FYI - you probably meant to name your class TapRecognizer. You misspelled recognizer and it is standard practice to name classes to start with uppercase letters. Method and variable names start with lowercase.
In your View controller
tapReconizer* reg = [[tapReconizer alloc]init];
[reg tapreg:self.view];
Here reg is getting deallocated, so make it is global for strong.
Declare it in your viewcontroller.h
#property (strong, nonatomic) TapReconizer* reg;
or in your .h or .m of view controller
after
#interface ViewController : UIViewController
{
TapReconizer* reg;
}
Hope it will help you.

Custom delegate not calling UITableViewController method

I have a custom UIButton class like below :
.h
#import <UIKit/UIKit.h>
#class FriendButton;
#protocol LongPressedButtonDelegate
- (void)buttonIsLongPressed:(FriendButton *)button;
#end
#interface FriendButton : UIButton
#property (nonatomic, weak) id<LongPressedButtonDelegate > delegate;
#end
.m
#implementation FriendButton
//this is called from the interface builder
-(id) initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:(NSCoder *)aDecoder];
NSLog(#"init called");
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:#selector(longPress:)];
[self addGestureRecognizer:longPress];
return self;
}
-(void)longPress:(id)sender {
NSLog(#"long press");
[self.delegate buttonIsLongPressed:self];
}
#end
My buttons are set up in the interface builder, they are contained in a UITableView cell. In my UITableViewController I have :
-(void)buttonIsLongPressed:(FriendButton *)button {
NSLog(#"Delegate method!");
}
and it controller conforms to protocol. The long press gesture works but the delegate method is not being called. I'm not sure why it's not working. Is it because I have to set each buttons delegate to the UITableViewController? If so how would I do that? The buttons are set up in the interface builder.
Define your UIButton property this way
#interface FriendButton : UIButton
#property (nonatomic, weak) IBOutlet id<LongPressedButtonDelegate > delegate;
#end
Then go to Interface Builder and right click on UIButton and you will see delegate link this delegate to UITableViewController. It should work
In your cellForRowAtIndexPath implementation in your UITableViewController you will need to do something like:
cell.button.delegate = self;
Edit: This is if you want to do it programmatically. Refer to the answers around IBOutlets if you want to do it in your storyboard.

calling selector for a gesture recognizer in another class via delegation

I have a custom view that uses a gesture recognizer that calls a method handleSingleTap. This works fine if the setup for the gesture recognizer and the selector it calls are in the same custom view (CircleView).However, I need the handleSingleTap method in the viewController, so I (1) created a protocol in the custom view (CircleView), (2) created the delegate property in the view, and when I (3)created the gesture recognizer, I set self.delegate for the target of handleSingleTap (rather than just self as it was initially). In the viewController.h, (4) I said that it conformed to the protocol and declared the method handleSingleTap. In the .m file of the view controller, I created a property for the custom view (CircleView) and then in viewDidLoad of the .m file, set self to be the delegate of the custom view. However, the handleSingleTap method is never getting called in the viewController when I tap on the circle in the custom view.
Can you explain why the selector handleSingleTap is not getting called in the viewController?
1) created protocol
#protocol CircleViewDelegate <NSObject>
-(void)handleSingleTap:(UITapGestureRecognizer *) tapper;
#end
2) created delegate property
#property (nonatomic, weak) id <CircleViewDelegate> delegate;
in CircleView
3) created gesture recognizer with target self.delegate
-(void)setUpGestureRecognizers{
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self.delegate action:#selector(handleSingleTap:)];
singleFingerTap.numberOfTapsRequired=1;
[self addGestureRecognizer:singleFingerTap];
}
4) in the viewController.h,
#interface ViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate, CircleViewDelegate>
-(void)handleSingleTap:(UITapGestureRecognizer *) tapper;
in the viewController.m
#property (strong, nonatomic) CircleView *overlay;
viewDidLoad
self.overlay.delegate = self;
This method in the viewController is not getting called
-(void)handleSingleTap:(UITapGestureRecognizer *) tapper {
NSLog(#"never getting called");
}
This is one solution for you. Of course you can do it with Selectors too, but this will work for sure too.
.h
#import <UIKit/UIKit.h>
#protocol CircleViewDelegate <NSObject>
#required
- (void) circleViewPressedByOneTap;
#end
#interface CircleView : UIView
#property (nonatomic,assign) id<CircleViewDelegate> delegate;
- (id)initWithFrame:(CGRect)frame andWithDelegate:(id<CircleViewDelegate>)del;
#end
.m:
#import "CircleView.h"
#interface CircleView () <UIGestureRecognizerDelegate>
#end
#implementation CircleView
#synthesize delegate;
- (id)initWithFrame:(CGRect)frame andWithDelegate:(id<CircleViewDelegate>)del
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
delegate = del;
[self setUpGestureRecognizers];
}
return self;
}
-(void)setUpGestureRecognizers{
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
singleFingerTap.numberOfTapsRequired=1;
[self addGestureRecognizer:singleFingerTap];
}
-(void)handleSingleTap:(UITapGestureRecognizer *) tapper{
[delegate circleViewPressedByOneTap];
}
And in your ViewController .m:
#import "YouClassViewController.h"
#import "CircleView.h"
#interface YouClassViewController () <CircleViewDelegate>
#end
#implementation YouClassViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
CircleView* yourCircleView = [[CircleView alloc] initWithFrame:CGRectMake(0, 0, 50, 50) andWithDelegate:self];
[self.view addSubview:yourCircleView];
}
- (void) circleViewPressedByOneTap{
NSLog(#"Yeaah you pressed it ! :) ");
}

app crashing when responding to tapgesture

Basically, I have a UIViewController with a xib built for holding content in a UIScrollView. this gets populated from an RSS feed. this works as expected. I want a tap on the UIView that the view controller owns to respond to a tap and continue on its way. however, a tap crashes the app with the "unrecognized selector sent to instance" error. I really have no clue what's going on.
The .h file of the xib's view controller looks like this:
#property (nonatomic,retain) IBOutlet UIImageView *article_image;
#property (nonatomic,retain) IBOutlet UILabel *article_title;
#property (nonatomic,retain) IBOutlet UILabel *article_date;
#property (nonatomic,retain) IBOutlet UIActivityIndicatorView *spinner;
#property (nonatomic,retain) NSString *preview_image;
- (void) loadPreviewImage;
Then the .m file looks like this:
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapGesture)];
singleTap.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:singleTap];
self.view.layer.shadowColor = [UIColor blackColor].CGColor;
self.view.layer.shadowOpacity = 0.6;
self.view.layer.shadowRadius = 1.5;
self.view.layer.shadowOffset = CGSizeMake(0, 0);
}
- (void) singleTapGesture:(UITapGestureRecognizer *)gesture {
NSLog(#"TAPPED!");
}
Even if I put just a simple roundrectbutton in the xib and attach it to an IBAction - it crashes, so I'm figuring there's something wrong with how my xib is set up, but I have no clue as to what. those properties in the .h get populated just fine from the VC that holds the scrollview, so the xib obviously knows the file it's associated with, so I just can't figure out why it's crashing and throwing that error on a tap.
The fix is this:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapGesture:)];
notice the : at the end of the selector.
Indeed, your action method signature is:
- (void) singleTapGesture:(UITapGestureRecognizer *)gesture;
while
#selector(singleTapGesture)
would rather identify:
- (void) singleTapGesture;
Hope this clarifies the issue.
well, i never really figured out exactly what was causing the crash - so i wound adding the gesture recognizer to the objects into the loop that builds them and all works great. not how i'd like to have done it (was trying to keep it in the object's class definition) but whatever. perhaps this will help someone else.

UIGestureRecognizer Crash

I am add to put a swipe up gesture to an image, but when swiped, app craches with BAD_EXEC error.
This is what I have:
.h file:
#interface MyViewController : UIViewController <UIGestureRecognizerDelegate>
{
UISwipeGestureRecognizer* swipeUpGesture;
IBOutlet UIImageView* myImage; //Connected from Interface Builder
IBOutlet UIScrollView* myScrollView;
}
#property (retain, nonatomic) UISwipeGestureRecognizer* swipeUpGesture;
#property (retain, nonatomic) IBOutlet UIImageView* myImage;
#property (retain, nonatomic) IBOutlet UIScrollView* myScrollView;
.m file:
- (void)viewDidLoad
{
//myImage is inside of myScrollView
swipeUpGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swiped)];
[swipeUpGesture setDirection:UISwipeGestureRecognizerDirectionUp];
[swipeUpGesture setDelegate:self];
[myImage addGestureRecognizer: swipeUpGesture];
}
- (void)swiped:(UISwipeGestureRecognizer*)sentGesture
{
NSLog (#"swiped");
}
So basically, within myView, I have myScrollView. Inside of myScrollView, I have myImage.
When I run above code, app runs until I swipe up, then it actually recognizes the swipe, but does not get to NSLog, crashes and I get BAD_EXEC.
Thanks in advance.
If you use addSubview, do the following:
[self addChildViewController:myViewController];
After that:
[self.view addSubView: myViewController.view];
Then use a UISwipeGestureRecognizer in the view controller.
You have a signature mismatch.
swipeUpGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swiped)];
Your selector is "swiped", without a colon, which means objective c runtime will try to find a method that takes "zero" parameter.
And since your "swiped" takes in a parameter, the runtime will fail to find a match when it tries to invoke the method and so crashes.
--
Change your #selector(swiped) to #selector(swiped:) and it should work.
You forgot a colon:
swipeUpGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swiped)];
should be
swipeUpGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swiped:)];
Without a colon, the Obj-C runtime will try to find a method without any arguments.
(As #Undo said, you forgot a colon.)
However, you can still get a EXC_BAD_ACCESS error if your ViewController was released before the touch event occurred.
This can happen when adding the view of ViewController as a subview to another view controller. e.g.
[mainViewController.view addSubview:self.view]
Where self is your MyViewController. You can check for this by adding a breakpoint into the
-(void)dealloc
method of your MyViewController. And checking if MyViewController is dealloced before your touch event.
You can fix this by adding a strong reference to MyViewController (ARC) wherever it is that you instantiate it.

Resources