Trouble with gesture recognizers in subviews - objective-c

I'm having a rather basic problem, I've looked around (here, google, etc) and haven't found a solution for this:
In my View Controller's viewDidLoad, I have this:
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(myfunc:)];
//I have a UIScrollView named "containerView"
//here's some code that creates an UIView in a variable named "myView"
//this works fine, I can see "myView" when I run it
[containerView addSubview:myView];
[myView addGestureRecognizer:longPress];
and then I have this function in the same class:
- (void)myfunc:(UIRotationGestureRecognizer *)recognizer
{
NSLog(#"hola!"); //never runs
}
The call to NSLog never runs. What am I doing wrong?
EDIT
Some extra info: it seems no touch events are ever sent to the subview. However, I tried adding an UIView with a button inside, all in the UIScrollView, and the button receives the touch event just fine, so the problem is only with programmatically added subviews.

Strangely enough, adding a "container" UIView inside the UIScrollView, and then the other subviews inside this container, made it work. Now touch events are sent to the subviews.

How can a superview interecept a touch sequence before any of its subviews?
TLDR:
[containerView setCanCancelContentTouches:NO];
do it just as you add the gesture recogniser to the scroll view.
also look into
[containerView setDelaysContentTouches:NO];
If the above behaviour isn't quite right.
for more info:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIScrollView_Class/Reference/UIScrollView.html

I think on myFunc you must do somethings like that:
switch (reconiger.state)
{
case UIGestureRecognizerBegin:
//Do something when start recognizer
break;
case UIGestureRecognizerEnd:
//Do something when end recognizer
break;
}

Related

Gesture recogniser does not works on tableView

The tableView was done programatically, and is listen to delegates .
the gestures :
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(didTapOnTableView:)];
[self.tableView addGestureRecognizer:tap];
-(void) didTapOnTableView:(UIGestureRecognizer*) recognizer
{
NSLog(#"ffff");
}
does not being called.
The problem is that UITableView has gesture recognizers of its own and they conflict with the ones you're adding. You can allow simultaneous processing of gesture recognizers by conforming your UIViewController subclass to <UIGestureRecognizerDelegate> protocol and implementing the following method gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:.
On the other hand, what you are trying to do is most probably wrong. Try using a UIButton object instead of the gesture recognizer, in 99% of the time that'll be enough.
this should be working, unless you are not tapping on the tableview, check is the tableview showing properly, or add break point to check is the gesture recogniser is added
Try to enable multitouch on the view using interface builder or this property multipleTouchEnabled.
if thats not what you are looking for you can use the delegate function for receiving touches:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return YES;
}
(if you go to the header of this file you can find similar delegates that might help)

UIGestureRecognizer blocking tableview scrolling

I have a table with static cells. One of these cells has a view in it with a pan gesture recogniser on it.
When I am scrolling down my tableview, when I get to the cell with the view with pan gesture recogniser, scrolling doesn't seem to work. If I touch outside the view (to the side or top or bottom) it works and I can scroll. I have an if statement in my gesturerecognizer that tests whether a certain area has been touched, and if so performs an action.
I have looked at this issue (http://stackoverflow.com/questions/3295239/uigesturerecognizer-blocking-table-view-scrolling) but setting cancelsTouchesInView to NO didn't work, I don't have anywhere setting the state property and using the method - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
I don't know where to get the 'otherGestureRecognizer' from or what object to call that method on.
I'm assuming I wan't to put my gesture recogniser as the first argument, and the tableview's scroll gesture recogniser as the otherGestureRecogniser, is that correct? If so, how do I get that?
UIPanGestureRecognizer *windPanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(moveWindHandle:)];
[self.windRangeView addGestureRecognizer:windPanGesture];
Then in my moveWindHandle:
-(void)moveWindHandle:(UIPanGestureRecognizer *)gesture
{
gesture.cancelsTouchesInView = NO;
isMovingHandle = [self isPoint:startedTouchAt insideHandle:_toHandleWindImageView];
if(isMovingHandle) {
if(gesture.state == UIGestureRecognizerStateBegan) {
//do stuff
}
}
else
{
//i want it to ignore this gesture and just scroll like normal if that is what hte user did
}
}
I have set the tableviewcontroller as a UIGestureRecognizerDelegate, but I don't know what to do with that.
You would not be the one calling -gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:. That method is called by the system. You need to set your table view controller as the delegate for your window pan gesture.
windPanGesture.delegate = self;
At that point, when you do the pan, the system will call the delegate method -gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: with your gesture recognizer as one argument and the scroll view's gesture recognizer as the other.
Update
You may also want to implement the -gestureRecognizerShouldBegin: method and return NO if you are not in one of the certain areas.

Adding UITapGestureRecognizer to UINavigationBar overrides ability to use ScrollToTop

So Ive added a TapGestureRecognizer to the navigation bar in order to "pull down" another view, thus its a UIPanGesture Recognizer. The problem is when this gesture is added the UITableView scrollToTop method no longer works, even if enabled before or after the addition of the gesture recognizer.
Has anyone ever experienced or can think of an easy solution?
Thanks!
Heres My Code:
if (!pan) {
_pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panaction:)];
[_pan setMaximumNumberOfTouches:1];
}
_pan.delegate = self;
[self.navigationController.navigationBar addGestureRecognizer:_pan];
EDIT:
Ok, the problem seems to be adding a UIView as a subview in order to drag down from the UINavigation bar, when I dont add the subview the scrollToTop works fine, once its added it must be intercepting the touch event underneath the status bar..

Using buttons on different views and classes to trigger view switch from the main view controller

I am using storyboard to create my page.. each with it's own class... from the mainViewController, I manage the view change with a swipe gesture recognizer... So far so good... But I have certain pages that will appear as "popup" when swiping up and to get rid of them, the user clicks on the X to remove the view... the thing is that doing this and releasing the view from superview is giving me a white screen as the switch is not done by the mainViewController, since the view is release by the popup class... I think I need to use some sort of delegation to do this.. but my brain just doesn't want to sink in how to use the delegate thing, even after reading about it...
Since the view switching is done on index 1, i'd figure that if I put those popup on index 2 and release them, the view at index 1 would still be there, but.. no..
... so at the beginning of my swipe gesture function, I start declaring the animation process... then I have a switch...case that check for the gesture being done.. left will set the animation to curlUP and right to Curl down... this is what happens after the switch... I also put myView into a myViewTemp, and add the new view to myView in the switch..case statement..
if (myView.title == #"popup1") {
[myView viewWillAppear:YES];
[myViewTemp viewWillDisappear:NO];
// [myViewTemp.view removeFromSuperview];
[self.view insertSubview:myView.view atIndex:2];
[myViewTemp viewDidDisappear:NO];
[myView viewDidAppear:YES];
} else {
[myView viewWillAppear:YES];
[myViewTemp viewWillDisappear:YES];
[myViewTemp.view removeFromSuperview];
[self.view insertSubview:myView.view atIndex:1];
[myView viewDidDisappear:YES];
[myViewTemp viewDidAppear:YES];
}
[UIView commitAnimations];
}

Trying to dismiss subview and UIView

I'm still very new to iOS developing. In fact, if there is a super noob, I would be one :p. Currently I am working on creating an IBAction button that accesses a subview. I have 2 ViewControllers, AddClientVC and NewClientVC, both with .nib files. So basically, inside my AddClientVC I implement an IBAction button with the following code:
- (IBAction)buttonPressed:(id)sender
{
UIView *transparentBG = [[UIView alloc] initWithFrame:CGRectMake(-5, -5, 1500, 2500)];
transparentBG.backgroundColor = [UIColor blackColor];
transparentBG.opaque = NO;
transparentBG.alpha = 0.5;
[self.view addSubview:transparentBG];
transparentBG.center = transparentBG.center;
vc = [[NewClientVC alloc] initWithNibName:#"NewClientVC" bundle:nil];
[self.view addSubview:vc.view];
vc.view.center = self.view.center;
}
As you can see I implemented a UIView as a transparent background. Basically AddClientVC --> Transparent Background --> NewClientVC. Now I have created another IBAction button but this time inside NewClientVC as a function to dismiss the accessed subview which looks like this:
- (IBAction)saveDismiss:(id)sender
{
[self.view removeFromSuperview];
}
The problem I'm having right now is when I click the saveDismiss button it only removes the subview that I called previously on AddClientVC but it didn't remove the transparent background I have created as a UIView. So the problem is how do I implement an action which simultaneously removes my subview and the UIView transparent background I created.
I need all the help I can get :)
I'm not too sure I fully understand what you want to happen, but maybe you could try something like this?
- (IBAction)saveDismiss:(id)sender
{
[vc removeFromSuperView];
[self.view removeFromSuperview];
}
I recommend not to manage your screens by adding subviews manually but instead use
- (void)presentModalViewController: (UIViewController *)modalViewController
animated: (BOOL)animated
method on your root viewController.
Or better instantiate a UINavigationController and use push and pop methods to drill down/up your views.
See apple reference here
Do not worry about code execution speed and stay confident in apple's SDK. UIKit is optimized for best user experience. Trying to boost your code by doing inappropriate SDK use is, in my opinion, a risky strategy. ;) – Vincent Zgueb
Sorry Vincent but I don't agree with you. I reached here because I want to implement an gesture that adds a sub-view for my view, which will be the navigation of my app.
[self.view addSubview:ctrl.view];
is faster presenting the view than
[self.navigationController presentModalViewController:ctrl animated:NO]
and by the way, the solution to the topic in my case was:
[self.view sendSubviewToBack:ctrl.view];