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"]; }
Related
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
I have three views,
View1 <-- View2 --> View3
Now View2 on leftSWipeGesture will send me to VIew3 while on right Gesture send to View1
My problem is, LeftGesture is working fine But not right gesture. I am using push Segue on both
Here is my Code
- (void) screenSwiped
{
[self performSegueWithIdentifier:#"tourSegue1" sender:self];
}
- (void) screenSwipedRight
{
[self performSegueWithIdentifier:#"tourSegue2" sender:self];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(screenSwiped)];
swipeLeft.numberOfTouchesRequired = 1;
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:swipeLeft];
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(screenSwipedRight)];
swipeRight.numberOfTouchesRequired = 1;
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swipeRight];
[super viewDidLoad];
}
The view structure you present at the start of your post is slightly misleading. From that little diagram it appears that you're already in View 2, and going to View 1 should be a "popViewController" if you're in a navigation controller.
So firstly - please verify this information and make sure you don't need to "popViewController" instead of performWithSequeIdentifier (because it doesn't work going backwards like that).
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
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.
Previously I've used the tap Detecting Window technique to detect taps in a UIWebView, but now I've tried to use gesture recognizers instead. The following code is in the viewDidLoad method of a view controller, which has a single UIWebView. This code compiles fine, but the handleTap method is never called. This seems like it should be simple.
// Configure a gesture recognizer to detect taps in the web view
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap)];
[self.myWebView addGestureRecognizer:singleTap];
[singleTap release];
[super viewDidLoad];
Set your view controller as the recognizer delegate:
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap)];
recognizer.delegate = self;
[self.myWebView addGestureRecognizer:recognizer];
And enable simultaneous gesture recognition (as the UIWebView probably sets a few recognizers itself, yours are skipped) :
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
Since the UIWebView does already handle a lot of touch events, it might be a bit tricky to add your own gesture recognizer.
I don't know if the user has to interact with your web view but you might try to add a UIView on top of the UIWebView and add the gesture recognizer to this view. It should still propagate unrecognized touch events to the underlying web view, thus leaving its interactivity intact.