delegates and gestureRecognizers for a UIView Subclass - iphone

I'm trying to create a UIView class that acts like a button. I want to do it entirely programmatically. I am able to get the button to appear but it is not clicking properly.
In my classes implementation file I have an initialization method as well as the following:
- (void)handlePress:(UILongPressGestureRecognizer *)sender{
if(sender.state == UIGestureRecognizerStateBegan){
NSLog(#"in handlePress");
}
}
In my view controller implementation file I have:
- (void)viewDidLoad
{
[super viewDidLoad];
self.button = [[buttonclass alloc] initButton];
[self.view addSubview: self.button];
UILongPressGestureRecognizer *singlePress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handlePress:)];
[self.button.buttonView addGestureRecognizer:singlePress];
}
(button being the instance variable of the class buttonclass and buttonView is just a subview of button)
I'm pretty sure the problem is within the lines:
UILongPressGestureRecognizer *singlePress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handlePress:)];
[self.button.buttonView addGestureRecognizer:singlePress];
I'm not even sure if these lines should go within the button initialization function or in the view controller implementation file. Should I add the following line?
singlePress.delegate = self;
I tried adding that line but I do not know where to put it and an error is saying that the delegate and self aren't the same type. Regardless, something is going wrong when I try to hook up the GestureRecognizer to the action or when I'm hooking the GestureRecognizer to the UIView button.
Any help would be greatly appreciated! Thanks and have a great day.

You should add the gesture on button and not on to the subview of button.
UILongPressGestureRecognizer *singlePress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handlePress:)];
[self.button addGestureRecognizer:singlePress];
There is no need to add following line:
singlePress.delegate = self;

In addition dont forget to release the Button object otherwise you will get an memory leak maybe in case you forget to clean up...
[super viewDidLoad];
self.button = [[buttonclass alloc] initButton];
[self.view addSubview: self.button];
[self.button release];
regards

Related

Why the UILongPressGestureRecognizer in custom UIWindow is not reflecting in UIWebview of the application?

I have implemented a custom UIWindow, this will be my main window. I have added a UILongPressGestureRecognizer to it. All the views in the application responds to this except the UIWebView. I am bit confused on this peculiar problem.
Below is the way of my implementation of UILongPressGestureRecognizer in UIWindow,
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
UILongPressGestureRecognizer* longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressAction:)];
[longPress setMinimumPressDuration:3];
[self addGestureRecognizer:longPress];
}
return self;
}
Could any one reason out for this problem? How to resolve this?
Thanks !
UIWebView has a scrollview inside it, with it's own gestures.
Basically, you have a reference to those gestures:
_webView.scrollView.panGestureRecognizer;
So, you can create a condition between those two gestures:
[_webView.scrollView.panGestureRecognizer requireGestureRecognizerToFail:_longGesture];
Haven't tried it myself, but maybe it will work.

Three gestures crash my iPhone

I have problem with swipe with three gestures
in my .m :
- (IBAction)click:(id)sender {
[_text setText:#"Hello World"];
}
- (IBAction)resetText:(id)sender {
[_text setText:#"Reset"];
}
when I clicked on the screen the output message "Hello World" will be shown on label
and it should shown "Reset" when I swipe three fingers from up to down, but it crashes
the weird thing is when I change the name of IBAction from "resetText" to for example "reset" or whatever name without capital letter it works. With any capital letter, it crashes
this is the Xcode file
I looked at your example project, and it seems that:
The crash only occurs on actual devices
The crash only occurs when the swipe gesture requires 3 or more touches
This looks to me like a bug in the UIGestureRecognizer class when added using Interface Builder, so there isn't much you can do about it now. I filed a radar (#14399827) with Apple describing this issue. You should probably do this as well.
However, you can work around this bug by creating the gesture recogniser in code instead of in the storyboard as you are now.
Remove the gesture recogniser from your storyboard (delete it completely), then add this to the viewDidLoad method in your view controller:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UISwipeGestureRecognizer *recogniser = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(resetText:)];
[recogniser setDirection:UISwipeGestureRecognizerDirectionDown];
[recogniser setNumberOfTouchesRequired:3];
[self.view addGestureRecognizer:recogniser];
}
I understand that this isn't ideal, as it may be more convenient in some cases to add the view controller directly to the storyboard, but unfortunately it seems that you can't currently do that due a bug in Apple's implementation.
I updated your view controller and now it is working for all gestures you want. Please check out and let me know.
- (void)viewDidLoad{
[super viewDidLoad];
//gesture for tap
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(click)];
[self.view addGestureRecognizer:tap];
//gesture for right swipe
UISwipeGestureRecognizer *rightRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(rightSwipeHandle:)];
rightRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
[rightRecognizer setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:rightRecognizer];
[rightRecognizer release];
//gesture for right swipe
UISwipeGestureRecognizer *leftRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(leftSwipeHandle:)];
leftRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
[leftRecognizer setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:leftRecognizer];
[leftRecognizer release];}
- (void)rightSwipeHandle:(UISwipeGestureRecognizer*)gestureRecognizer{ [_text setText:#" World"]; }
- (void)leftSwipeHandle:(UISwipeGestureRecognizer*)gestureRecognizer{ [_text setText:#"World"]; }
- (void)click{ [_text setText:#"Hello World"]; }

Trouble applying gesture recognizer to navigationbar

In my iPad Application I have multiple views on a screen.
What I want to do is apply a double tap Gesture Recognizer to the Navigation Bar. But I had no success, however when the same gesture recognizer applied to that view it works.
Here is the code I am using:
// Create gesture recognizer, notice the selector method
UITapGestureRecognizer *oneFingerTwoTaps =
[[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(oneFingerTwoTaps)] autorelease];
// Set required taps and number of touches
[oneFingerTwoTaps setNumberOfTapsRequired:2];
[oneFingerTwoTaps setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:oneFingerTwoTaps];
This works on view, but when this is done:
[self.navigationController.navigationBar addGestureRecognizer:oneFingerTwoTaps]
doesn't work.
For anyone else viewing this, here is a much simpler way to do this.
[self.navigationController.view addGestureRecognizer:oneFingerTwoTaps];
For this you need to subclass UINavigationBar, override the init button in it and add your gesture recognizer there.
So say you make a subclass called 'CustomNavigationBar' - in your m file you would have an init method like this:
- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super initWithCoder:aDecoder]))
{
UISwipeGestureRecognizer *swipeRight;
swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(didSwipeRight:)];
[swipeRight setDirection:UISwipeGestureRecognizerDirectionRight];
[swipeRight setNumberOfTouchesRequired:1];
[swipeRight setEnabled:YES];
[self addGestureRecognizer:swipeRight];
}
return self;
}
Then you need to set the class name of your navigation bar in interface builder to the name of your subclass.
Also it's handy to add a delegate protocol to your navigation bar to listen for methods sent at the end of your gestures. For example - in the case of the above swipe right:
#protocol CustomNavigationbarDelegate <NSObject>
- (void)customNavBarDidFinishSwipeRight;
#end
then in the m file - on the gesture recognised method (whatever you make it) you can trigger this delegate method.
Hope this helps

UIImageView showing UIPopOver

I would like to fire up this event:
- (IBAction)profilePop:(id)sender
{
ProfileViewController * profile = [[ProfileViewController alloc] init];
UIImageView * temp = ((UIImageView *)sender);
profile.uid = [[[posts objectAtIndex:((UIImageView *)sender).tag] creator] mid];
NSLog(#"profile id %#", profile.uid);
UIPopoverController * profilePop = [[UIPopoverController alloc] initWithContentViewController:profile];
[profilePop presentPopoverFromRect:CGRectMake(temp.frame.origin.x+temp.frame.size.width, temp.frame.origin.y + temp.frame.size.height/2, profile.view.frame.size.width, profile.view.frame.size.height) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
}
when a user taps on an UIImageView. All I am trying to do is to show a popover when an UIImageView is clicked and it is shown to the right of the UIImageView. I see that UIImageView doesn't have an addAction attribute from it as it's not a subclass of UIControl. I did some research that I might probably have to use a UIButton instead. Is this true? Is there a way to do this using UIImageView so I don't have to rewrite the code again? I
First.
you could get the touch on any object, which has super class as UIView.
if you see the UIImageView in apple documentation.
UIView : UIResponder : NSObject
UIResponder has function to get the touches. So implement the below functions in your view class and detect the touches on your UIImageView .
– touchesBegan:withEvent:
– touchesMoved:withEvent:
– touchesEnded:withEvent:
– touchesCancelled:withEvent:
Second:
you could also create the UITapGestureRecognizer for UIImageView.
Check the below blog tutorial.
Working with UIGestureRecognizers
EDITED:
Use below code :
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped:)];
[tapRecognizer setNumberOfTapsRequired:1];
[tapRecognizer setDelegate:self];
[MyImageView addGestureRecognizer:tapRecognizer];
if user tap once, tapped function will be called , So you tabbed function implemntation should be look like below
-(void)tapped:(id)sender
{
NSLog(#"See a tap gesture");
ProfileViewController * profile = [[ProfileViewController alloc] init];
UIImageView * temp = [(UIPanGestureRecognizer*)sender view];
profile.uid = [[[posts objectAtIndex:((UIImageView *)sender).tag] creator] mid];
NSLog(#"profile id %#", profile.uid);
UIPopoverController * profilePop = [[UIPopoverController alloc] initWithContentViewController:profile];
[profilePop presentPopoverFromRect:CGRectMake(temp.frame.origin.x+temp.frame.size.width, temp.frame.origin.y + temp.frame.size.height/2, profile.view.frame.size.width, profile.view.frame.size.height) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
}
What about using an UIButton instead and using the class method to add your UIImage to it.
- (void)setImage:(UIImage *)image forState:(UIControlState)state
You can define a UIButton of type custom, don't give it any text or image, give it a clear background, and the same frame as your image view. Then add your target/selector to the button and it will appear to the user they are tapping the image view, when they are actually tapping an invisible button. This should take about 3 minutes to set up in IB, so I don't think you'll need to rewrite your code again.
You could create a Tap Gesture recognizer and attach it to the UIImageView.
// By now imageView exists!
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapGesture:)];
tapGesture.numberOfTapsRequired = 1;
tapGesture.numberOfTouchesRequired = 1;
[imageView addGestureRecognizer:tapGesture];
[tapGesture release];
Now the handleTapGesture will be quite similar to your -profilePop:
Since you are talking of pop over controllers, I assume you already have gesture recognizers available.

UIGestureRecognizer only works on One class

I have a number of classes and want to add a UIGestureRecognizer to their UIImageViews.
I add one correctly to all the classes. Thing is I duplicate code so that each class is adding the same recognizer. These are local recognizers
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget : self action : #selector (handleSingleTap:)];
[singleTap setNumberOfTapsRequired:1];
[background addGestureRecognizer:singleTap];
[singleTap release];
so it should still work for each class.
The problem is that it only works on the first class, not on the others.
background is the UIImageView and is present in every class. So I have multiple backgrounds.
I present each new ModelViewController class, is this maybe what the issue is?
I use the recognizer as follows
- (void) handleSingleTap : (UIGestureRecognizer*) sender
{
//do whatever
}
Each class also implements the
#interface Someclass : UIViewController <UIGestureRecognizerDelegate>
Im not sure why it isnt working though. I have a print out in each handleSingleTap method. and nothing gets printed.
First
Are you adding the same recognizer object to different views? If so that won't work. UIGestureRecognizer objects only detect/track gestures in one view. So make sure you have a different recognizer object for each of your views like:
UITapGestureRecognizer *r1 = [UITapGestureRecognizer alloc] initWithTarget:self action:...];
[view1 addGestureRecognizer:r1];
[r1 release];
UITapGestureRecognizer *r2 = [UITapGestureRecognizer alloc] initWithTarget:self action:...];
[view2 addGestureRecognizer:r2];
[r2 release];
...
Second Make sure the view (in this case UIImageView) is [uiimageview setUserInteractionEnabled:YES];
Third If you are just detecting simple touches then is not necessary to adopt UIGestureRecognizerDelegate protocol, so just delete that protocol from the #interface
Hope it helps