UIScreenEdgePanGestureRecognizer in Objective-C - ios

I am learning objective-c and do not know what this code does. I understand what UIScreenEdgePanGestureRecognizer does. However, I am confused as to what this code is doing with the UIScreenEdgePanGesture.
UIScreenEdgePanGestureRecognizer *rightRecog =
[[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:#selector(resetChart:)];
[rightRecog setEdges:UIRectEdgeRight];
[rightRecog setCancelsTouchesInView:YES];
[self.chartView addGestureRecognizer:rightRecog];
UIScreenEdgePanGestureRecognizer *leftRecog = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:#selector(resetChart:)];
[leftRecog setEdges:UIRectEdgeLeft];
[leftRecog setCancelsTouchesInView:YES];
[self.chartView addGestureRecognizer:leftRecog];

This is a code pattern used to define a UIPanGestureRecognizer that checks for finger/pen touches on the devices screen edges from right inside and from left inside the screen center but will cancel any touch event happening inside the view the same time.
The recognizer binds to self.chartView to observe those gestures.
It also defines a method #selector(resetChart:) that will act (action) in case the fingers are sliding in on one side of the chartView. But the method -resetChart: will be part of the ViewController Class or View Class you defined the recogniser inside defined as (self).
UIScreenEdgePanGestureRecognizer *rightRecog =
[[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:#selector(resetChart:)];
[rightRecog setEdges:UIRectEdgeRight];
[rightRecog setCancelsTouchesInView:YES];
[self.chartView addGestureRecognizer:rightRecog];
the above code is setting up the recognizer from the right side.
The code below does the same thing for the left side but will trigger the same method.
UIScreenEdgePanGestureRecognizer *leftRecog = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:#selector(resetChart:)];
[leftRecog setEdges:UIRectEdgeLeft];
[leftRecog setCancelsTouchesInView:YES];
[self.chartView addGestureRecognizer:leftRecog];
so it could be melt together like so..
UIScreenEdgePanGestureRecognizer *rightLeftRecog =
[[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:#selector(resetChart:)];
[rightLeftRecog setEdges:UIRectEdgeRight|UIRectEdgeLeft];
[rightLeftRecog setCancelsTouchesInView:YES];
[self.chartView addGestureRecognizer:rightLeftRecog];
because -resetChart: is just doing the same.
which will look like
-(void)resetChart:(UIScreenEdgePanGestureRecognizer*)gesture {
//do some stuff with the gesture or amount of fingers used.
}

Related

UIPanGesture and UISwipeGesture in the same view

I have a UIView that already has a UIPanGesture implemented that works when a user drags the UIView half way up causing some action. As of now, it works just fine. Now, within the same UIView I want to implement a a UISwipeGesture so when the user swipes up, some other method would be called. I've been reading about the UIGestureRecognizerDelegate methods and I'm thinking I need to use gestureRecognizer:shouldRequireFailureOfGestureRecognizer: but I'm not sure.
I implemented the following in my viewDidLoad and got an error saying "invalid argument. Unrecognized selector sent to instance"
UIPanGestureRecognizer * panRec = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
panRec.delegate = self;
[panedView addGestureRecognizer:panRec];
UISwipeGestureRecognizer * swipeRec = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipe:)];
swipeRec.direction = UISwipeGestureRecognizerDirectionUp;
swipeRec.delegate=self;
[panedView addGestureRecognizer:swipeRec];
[self gestureRecognizer:swipeRec shouldRequireFailureOfGestureRecognizer: panRec];
gestureRecognizer:shouldRequireFailureOfGestureRecognizer: is a delegate of the the UIGestureRecognizer. Meaning , you will implement the method , and when a gesture happens this method will be called automatically . To enable the gesture recognisers calling this method you need to set the gesture recogniser delegate to self, this can be done in viewDidLoad.

Can't get UISwipeGestureRecognizer to work

I'm making a sidebar on my app so that when you swipe right it opens, I am using this code in the object I made called sidebar:
_swipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self.superview action:#selector(swiped)];
[_swipeRecognizer setDirection: UISwipeGestureRecognizerDirectionRight];
[self.superview addGestureRecognizer:_swipeRecognizer];
And this of course crashes and throws the error:
[UIView swiped]: unrecognized selector sent to instance 0x1fdbd0c0
because it's looking for the "swiped" method on self.superview when I want it to look for the method on self, but I want the gesture to be detected on self.superview.
I'm also confused, if I set initWithTarget then why do I have to do addGestureRecognizer? What's the difference between those two things?
Change this:
_swipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self.superview action:#selector(swiped)];
to:
_swipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swiped)];
The call to initWithTarget:action: specifies the class that gets told about the gesture events. The "target" must implement the "action" method.
The call to addGestureRecognizer: specifies which view the gesture must happen on.
In many cases these are the same but in your case they are different.
if you want to handle the gesture recognized in self, at first line, you should set self as the the receiver, not self.superview:
_swipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swiped)];
then implement the swiped action:
-(void)swiped:(UIGestureRecognizer *)gestureRecognizer {
//enter code here
}

slide the finger from right to left, or vice versa :-)

I am working on application for jokes and I have one feature still missing which is showing jokes text view on the same way of showing photos in Iphone, one by one, and having the user slide the finger from right to left, or vice versa :
Does anyone has an example or knows of one?
You're looking for a UIPageViewController if I'm understanding what you're asking.
Setting up a UIPageViewController is pretty easy.
UIPageViewController *pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
Then simply set the delegate, and create the respective delegate methods, and you're all set!
delegate methods can be referenced from UIPageViewController's class reference.
Good luck! And welcome to Stack Overflow!
Do this for detecting swipes:
UISwipeGestureRecognizer *swipeLeftRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFrom:)];
swipeLeftRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
UISwipeGestureRecognizer *swipeRightRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFrom:)];
swipeLeftRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
// Add it to the view you want
[self.view addGestureRecognizer:swipeLeftRecognizer];
[self.view addGestureRecognizer:swipeRightRecognizer];
//the handler code:
- (void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer {
if (recognizer.direction == UISwipeGestureRecognizerDirectionLeft) {
//do something when swiped left.
}
else if (recognizer.direction == UISwipeGestureRecognizerDirectionRight)
{
//do something when swiped right.
}
}

Gesture Recognizers and Blocks

Can we use blocks with Gesture Recognizers? It doesn't appear so. For example, this does not work:
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget: self
action:^(id sender) {
}
];
Am I missing something, or are blocks just not supported by the UIGestureRecognizer class?
However, this should:
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:[^{
// do stuff
} copy] action:#selector(invoke)];
You shouldn't probably do this, however, since it's a private method.

UITapGestureRecognizer initWithTarget:action: method to take arguments?

I'm using UITapGestureRecognizer because I'm using a UIScrollView that acts as a container for my UILabels. Basically I'm trying to use an action method with arguments so I can e.g. send myLabel.tag value to the action method to know what action to take depending on what UILabel has has been triggered by a tap.
One way of doing it is having as many action methods as UILabels but that isn't very "pretty" codewise. What I would like to achieve is just having one action method with switch statements.
Is this possible or will I have to do it like this (sigh):
UITapGestureRecognizer *myLabel1Tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(myLabel1Tap)];
[myLabel1Tap addGestureRecognizer:myLabel1Tap];
UITapGestureRecognizer *myLabel2Tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(myLabel2Tap)];
[myLabel1Tap addGestureRecognizer:myLabel2Tap];
UITapGestureRecognizer *myLabelNTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(myLabelNTap)];
[myLabel1Tap addGestureRecognizer:myLabelNTap];
- (void)myLabel1Tap {
// Perform action
}
- (void)myLabel2Tap {
// Perform action
}
- (void)myLabelNTap {
// Perform action
}
Add a single gesture recognizer to the view that is the superview of your various labels:
UITapGestureRecognizer *myLabelTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(myLabelTapHandler:)];
[myLabelParent addGestureRecognizer:myLabelTap];
Then when you handle the gesture, determine which label was tapped:
-(void)myLabelTapHandler:(UIGestureRecognizer *)gestureRecognizer {
UIView *tappedView = [gestureRecognizer.view hitTest:[gestureRecognizer locationInView:gestureRecognizer.view] withEvent:nil];
// do something with it
}
You can use just one UITapGestureRecognizer and in your gesture handler (your myLaberXTap), which has the syntax:
- (void)handleGesture:(UITapGestureRecognizer*)gestureRecognizer {
...
}
use gesture.view to know which view you are working on.

Resources