UILongPressGestureRecognizer not working after archiving application - ios

When testing in iPad, I can successfully call the method attached to UILongPressGestureRecognizer in UILabel.
After I have archived the application for Enterprise deployment, UILongPressGestureRecognizer does not work anymore.
I have already added the following codes aside from manually ticking User Interaction Enabled:
In .h file:
#interface BGMSetMenuViewController : UIViewController <UIGestureRecognizerDelegate>
In .m file:
- (void)viewDidLoad
{
[super viewDidLoad];
itemPriceLabel.userInteractionEnabled = YES;
itemNameLabel.userInteractionEnabled = YES;
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressSetMenuPrice:)];
longPress.delegate = self;
[itemPriceLabel addGestureRecognizer:longPress];
}
#pragma mark - UILongPressGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
- (void)longPressSetMenuPrice:(UILongPressGestureRecognizer*)gesture
{
if (gesture.state == UIGestureRecognizerStateEnded) {
BGMPasscodeViewController *passcodeVC = [[BGMPasscodeViewController alloc] initWithNibName:#"BGMPasscodeViewController" bundle:nil];
self.providesPresentationContextTransitionStyle = YES;
self.definesPresentationContext = YES;
[passcodeVC setModalPresentationStyle:UIModalPresentationOverCurrentContext];
[self presentViewController:passcodeVC animated:YES completion:nil];
}
}
Anybody here who have the same experience?
Please note that this was working in Xcode 7 and iOS 9.
Now, I'm using Xcode 8 and testing in iOS 10.0.2 and it doesn't work anymore.

Try below code:set YES to label userIntractionEnabled also in storyboard
- (void)viewDidLoad {
[super viewDidLoad];
labelTouch.userInteractionEnabled = YES;
[self labelLongPressed:labelTouch];}
- (void)labelLongPressed:(UILabel *)label{
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handleLongPress:)];
longPress.minimumPressDuration = 2; //seconds
longPress.delegate = self;
[label addGestureRecognizer:longPress];}
-(void) handleLongPress : (UITapGestureRecognizer *)sender{
UIButton *button = (UIButton *)sender.view;
NSLog(#"longpress");}

Related

The action of GestureRecognizer does not fire

I add the gesture to view as following steps:
#interface iCarousel () <UIGestureRecognizerDelegate>
{
UIPanGestureRecognizer * mPanGesture;
UITapGestureRecognizer * mTapGesture;
}
#end
#implementation iCarousel
- (void)setUp
{
_contentView = [[UIView alloc] initWithFrame:self.bounds];
_contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
/
mPanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(iCarouselDidPan:)];
mPanGesture.delegate = self;
[_contentView addGestureRecognizer:mPanGesture];
/
mTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(iCarouselDidTap:)];
mTapGesture.delegate = self;
[_contentView addGestureRecognizer:mTapGesture];
/
self.accessibilityTraits = UIAccessibilityTraitAllowsDirectInteraction;
self.isAccessibilityElement = YES;
[self addSubview:_contentView];
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super initWithCoder:aDecoder]))
{
[self setUp];
}
return self;
}
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]))
{
[self setUp];
}
return self;
}
...
- (void)iCarouselDidTap:(UITapGestureRecognizer *)tapGesture
{
...
}
- (void)iCarouselDidPan:(UIPanGestureRecognizer *)panGesture
{
...
}
...
#end
Now, the method in this class
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gesture
return me YES
But, the actions iCarouselDidPan: and iCarouselDidTap: do not fire.
The information is printed in gestureRecognizerShouldBegin: method.
(lldb) po _contentView.gestureRecognizers
<__NSArrayI 0x1572bec0>(
<UIPanGestureRecognizer: 0x16dea750; state = Possible; view = <UIView 0x16dea640>; target= <(action=iCarouselDidPan:, target=<iCarousel 0x16dea1b0>)>>,
<UITapGestureRecognizer: 0x16e8f310; state = Possible; view = <UIView 0x16dea640>; target= <(action=iCarouselDidTap:, target=<iCarousel 0x16dea1b0>)>>
)
(lldb) po gesture
<UIPanGestureRecognizer: 0x16dea750; state = Possible; view = <UIView 0x16dea640>; target= <(action=iCarouselDidPan:, target=<iCarousel 0x16dea1b0>)>>
It's only happened on devices <4s 9.3.x , 5 10.3.1> at current moment.
Try implement the following methods of protocol UIGestureRecognizerDelegate inside your iCarousel:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch {
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceivePress:(UIPress *)press {
return YES;
}
Possible cases for not working gestures .
1 - You need to enable interaction of view.
[_contentView setUserInteractionEnabled:YES];
2 - Add this delegate in your class.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
Declare UIGestureRecognizerDelegate in .h file
Gesture definition
-(UITapGestureRecognizer*)setTapGesture{
UITapGestureRecognizer *Tap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleTapWithGestureRecognizer:)];
Tap.delegate = self;
return Tap;
}
-(void)handleTapWithGestureRecognizer:(UITapGestureRecognizer *)TapGestureRecognizer{
NSLog(#"tap Gesture");
}
-(UIPanGestureRecognizer*)setpanGesture{
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[panRecognizer setMinimumNumberOfTouches:1];
[panRecognizer setMaximumNumberOfTouches:1];
return panRecognizer;
}
- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
[self.view bringSubviewToFront:recognizer.view];
CGPoint touchLocation = [recognizer locationInView:self.view];
self.YOURVIEW.center = touchLocation;
}
Call Gesture or add gesture to your view
[self.YOURVIEW addGestureRecognizer:[self setTapGesture]];
[self.YOURVIEW addGestureRecognizer:[self setpanGesture]];
self.YOURVIEW.userInteractionEnabled = YES;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
Good Luck
Happy Coding.

iOS - Copying a UITextView

In my app users can send messages to each other. I use UITextView inside of a bubble image to display the chat history.
[messageTextView setFrame:CGRectMake(padding, padding+5, size.width, size.height+padding)];
[messageTextView sizeToFit];
messageTextView.backgroundColor=[UIColor clearColor];
UIImage *img = [UIImage imageNamed:#"whiteBubble"];
UIImageView *bubbleImage=[[UIImageView alloc] initWithImage:[img stretchableImageWithLeftCapWidth:24 topCapHeight:15]];
messageTextView.editable=NO;
[bubbleImage setFrame:CGRectMake(padding/2, padding+5,
messageTextView.frame.size.width+padding/2, messageTextView.frame.size.height+5)];
[cell.contentView addSubview:bubbleImage];
[cell.contentView addSubview:messageTextView];
Currently, when a user holds down on the message text, they see the 'Copy' and 'Define' options with cursors to select text.
However, I would rather have the basic iOS messaging option of holding down on a chat bubble to copy the entire message. How can this be achieved?
I would subclass UITextView to implement your own version of the copy menu. You can do it a number of ways, but one possible way is like below.
The basic idea is that the text view sets up a UILongPressGestureRecognizer that will create the popup menu when a long press is detected.
UILongPressGestureRecognizer has several default system menus that will show up unless you tell them not to. The way to do that is to return NO for any selectors that you don't want to handle in canPerformAction:withSender:. In this case, we're returning NO for any selector except for our custom copyText: selector.
Then that selector just gets a reference to the general UIPasteboard and sets it's text to the text of the TextView.
In your subclass's implementation:
#implementation CopyTextView
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self setup];
}
return self;
}
- (instancetype)init
{
self = [super init];
if (self) {
[self setup];
}
return self;
}
- (void)setup {
self.editable = NO;
self.selectable = NO;
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressDetected:)];
longPress.minimumPressDuration = 0.3f; // however long, in seconds, you want the user to have to press before the menu shows up
[self addGestureRecognizer:longPress];
}
- (void)longPressDetected:(id)sender {
[self becomeFirstResponder];
UILongPressGestureRecognizer *longPress = (UILongPressGestureRecognizer *)sender;
if (longPress.state == UIGestureRecognizerStateEnded) {
UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:#"Copy" action:#selector(copyText:)];
UIMenuController *menuCont = [UIMenuController sharedMenuController];
[menuCont setTargetRect:self.frame inView:self.superview];
menuCont.arrowDirection = UIMenuControllerArrowDown;
menuCont.menuItems = [NSArray arrayWithObject:menuItem];
[menuCont setMenuVisible:YES animated:YES];
}
}
- (BOOL)canBecomeFirstResponder { return YES; }
- (void)copyText:(id)sender {
UIPasteboard * pasteboard = [UIPasteboard generalPasteboard];
[pasteboard setString:self.text];
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (action == #selector(copyText:)) return YES;
return NO;
}
#end
Useful documentation:
UILongPressGestureRecognizer Documentation
UIMenuController Documentation

Objective C Subclass UITextField to copy only

I'm trying to create a class that makes a read only text field that allows the user to copy its contents. Here is my code:
CopyOnly.h
#import <UIKit/UIKit.h>
#interface CopyOnly : UITextField
#end
CopyOnly.m
#import "CopyOnly.h"
#implementation CopyOnly
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self attachTapHandler];
}
return self;
}
- (void) attachTapHandler
{
[self setUserInteractionEnabled:YES];
UIGestureRecognizer *touchy = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[self addGestureRecognizer:touchy];
}
- (BOOL) canPerformAction: (SEL) action withSender: (id) sender
{
return (action == #selector(copy:));
}
- (void) handleTap: (UIGestureRecognizer*) recognizer
{
[self becomeFirstResponder];
UIMenuController *menu = [UIMenuController sharedMenuController];
[menu setTargetRect:self.frame inView:self.superview];
[menu setMenuVisible:YES animated:YES];
}
- (void)copy:(id)sender
{
UIPasteboard *board = [UIPasteboard generalPasteboard];
[board setString:self.text];
self.highlighted = NO;
[self resignFirstResponder];
}
- (BOOL) canBecomeFirstResponder
{
return YES;
}
#end
This works great, only the keyboard is coming up. I don't want any keyboard to come up.
I tried adding this to initWithFrame:
UIView* noKeyboard = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
self.inputView = noKeyboard;
This does not give me the result I'm expecting. Anyone know how I can do this?
Extending on my comment. This is easily accomplished using a UITextView (not UITextField) with editable property set to NO.
UITextView* tf = [[UITextView alloc] initWithFrame:CGRectMake(50, 50, 200, 50)];
tf.editable = NO;
tf.text = #"Hey this is a test!";
[self.view addSubview:tf];
Adding this to -(BOOL)canBecomeFirtResponder seemed to do the trick. Hacky, but it works.
- (BOOL) canBecomeFirstResponder
{
UIView* noKeyboard = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
self.inputView = noKeyboard;
return YES;
}
If you stuck with text field that doesn't allow editing try totally different approach. Follow instructions in this article http://nshipster.com/uimenucontroller/ to implement UILabel that supports copying.

how to hide keyboard when tap background [duplicate]

This question already has answers here:
iOS - Dismiss keyboard when touching outside of UITextField
(38 answers)
Closed 8 years ago.
I have one TableViewCell that has UITextField in it.
I want when click out of UITextField hidden keyboard but I don't about that.
this is my code:
#implementation TextFieldCell
#synthesize Textfield,placeholder;
- (void)awakeFromNib
{
// Initialization code
Textfield = [self makeTextField];
[self addSubview:Textfield];
placeholder = [self PlaceHolderLabel];
[self addSubview:placeholder];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (UITextField *)makeTextField
{
CGRect TextFrame = CGRectMake(0,0,300,80);
UITextField *textfield = [[UITextField alloc]initWithFrame:TextFrame];
textfield.delegate = self;
textfield.textColor = [UIColor colorWithRed:0/256.0 green:84/256.0 blue:129/256.0 alpha:1.0];
textfield.backgroundColor = [UIColor yellowColor];
textfield.placeholder = [NSString stringWithFormat:#"Mamal"];
UIView *spacerleftView = [[UIView alloc] initWithFrame:CGRectMake(0,0,20,20)];
UIView *spacerrightView = [[UIView alloc] initWithFrame:CGRectMake(0,0,20,20)];
[textfield setLeftViewMode:UITextFieldViewModeAlways];
[textfield setRightViewMode:UITextFieldViewModeAlways];
textfield.leftView = spacerleftView;
textfield.rightView = spacerrightView;
return textfield;
}
- (UILabel *)PlaceHolderLabel{
NSString *labelText = Textfield.placeholder;
Textfield.placeholder = nil;
CGRect labelFrame = CGRectMake(0,0,280,80);
UILabel *placeholderLabel = [[UILabel alloc] initWithFrame:labelFrame];
[placeholderLabel setTextColor:[UIColor lightGrayColor]];
[placeholderLabel setText:labelText];
placeholderLabel.textAlignment = NSTextAlignmentRight;
return placeholderLabel;
}
- (UILabel *)clearPlaceHolderLabel{
NSString *labelText = nil;
CGRect labelFrame = CGRectMake(0,0,280,80);
UILabel *placeholderLabel = [[UILabel alloc] initWithFrame:labelFrame];
[placeholderLabel setText:labelText];
return placeholderLabel;
}
-(void)textFieldDidBeginEditing:(UITextField *)textField {
//Keyboard becomes visible
//perform actions.
NSLog(#"start");
}
-(void)textFieldDidEndEditing:(UITextField *)textField{
NSLog(#"end");
}
Add gesture recogniser in viewDidLoad :
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(closeKeyboard:)];
[self.view addGestureRecognizer:tap];
and then implement closeKeyboard:
- (IBAction)closeKeyboard:(id)sender {
[self.view endEditing:YES];}
my friend I had this problem but I can solve that.
you don't need add UITextField in TableViewCell , you can create TextField in ViewController or TableViewController that your tableView is inner it and then add TextField inside any cell that you want.
like this code:
ViewController.h
#interface ViewController : UIViewController <UITableViewDataSource,UITableViewDelegate,UITextFieldDelegate>
#property (nonatomic,strong) UITableView *table;
#property (weak,nonatomic) UITextField *Textfield;
ViewController.m
#implementation ViewController
#synthesize table,Textfield;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//add table in view
table = [self makeTableView];
[self.view addSubview:table];
[self.view setBackgroundColor: RGB(193,60,46)]; //will give a UIColor objct
//run textfield programmatically
Textfield = [self makeTextField];
//hide keyboard with hideKeyboard selector
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideKeyboard)];
[self.table addGestureRecognizer:gestureRecognizer];
}
- (void) hideKeyboard {
[Textfield resignFirstResponder];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
Try to use
[self.view setEditing:YES];
in -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
try this:
// somewhere in viewDidLoad
UITapGestureRecognizer * tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapOnBackground)];
[self.view addGestureRecognizer:tapRecognizer];
self.view.userInteractionEnabled = YES;
// ...
- (void)tapOnBackground
{
[self.view endEditing:YES];
}
Add this code in your textField implementation method.
//Set to Remove Keyboard from view
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
After that create dismissKeyboard method.
//First Responder Remove Keyboard
-(void)dismissKeyboard {
[Textfield resignFirstResponder];
}

Not getting button action/ Single tap on custom MKannotation call out view

I have created a custom annotation and a call out for my map view. I need to navigate to another view when the user clicks on call out view or he clicks to the button that added as sub view to the callout view. But both gesture recognizer and add target is not working for me in this case. The setSelected: method was invoked and the view get hidden when tap occurs in call out view.
#interface VBPunchCardAnnotation : MKAnnotationView{
UIView *calloutView;
}
- (id)initWithAnnotation:(id )annotation reuseIdentifier:(NSString *)reuseIdentifier deal:(id)punchdeal
{
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
calloutView = [[UIView alloc] init];
calloutView.hidden = YES;
infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[calloutView addSubview:infoButton];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(annotationTapped:)];
singleTap.numberOfTapsRequired = 1;
singleTap.delegate = self;
[calloutView addGestureRecognizer:singleTap];
[infoButton addTarget:self action:#selector(annotationTapped:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:calloutView];
return self;
}
-(void)setSelected:(BOOL)selected animated:(BOOL)animated
{
// show/hide callout and swap pin image
calloutView.hidden = !selected;
self.image = !selected ? normalPin : selectedPin;
// dispatch an event to alert app a pin has been selected
if(selected) [[NSNotificationCenter defaultCenter] postNotificationName:#"punchCardAnnotation" object:self];
}
-(void)annotationTapped:(id)sender{
[self.delegate punchCardAnnotationClickedForDeal:self.punchDeal];
}
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
UIView* hitView = [super hitTest:point withEvent:event];
if ([hitView isKindOfClass:[UIButton class]]) {
}
}
Finally I got the answer. It;s here
Followed this tutorial. Really great solution.
https://github.com/nfarina/calloutview
Happy coding!!

Resources