user6631314
user6631314

Reputation: 1966

IOS/Objective-C: Detect Taps Using UITapRecognizer from View that Changes in Size

Edited

I have a textview with a UITapGestureRecognizer to identify words on which people tap. The UITextVIew itself, however, changes in size based on the quantity of text loaded in the textView. Right now the textView is not recognizing any taps that occur on text in textview beyond the initial size of the screen.

The tap recognizer is currently initialized in viewDidLoad as I only want to create it once. It is therefore created before the view is laid out. Should I move it to viewwillappear or some other method that fires after the size of the textview is known? Or is there a way to let the tapRecognizer know the textview is now larger?

The screen uses autplayout so this may be part of the problem.

//This is how the recognizer is created in viewdidload:
 UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc]initWithTarget:self
 action:@selector(handleTap:)];
    tapList.cancelsTouchesInView = NO;
    [self.myView addGestureRecognizer:tapRec];

//This is method that handles tap
- (void) handleTap:(UITapGestureRecognizer *)recognizer{
     UITextView *textView =  (UITextView *)recognizer.view;
    CGPoint location = [recognizer locationInView:textView];
     CGPoint position = CGPointMake(location.x, location.y);
      UITextPosition *tapPosition = [textView closestPositionToPoint:position];
      UITextRange *textRange = [textView.tokenizer rangeEnclosingPosition:tapPosition withGranularity:UITextGranularityLine inDirection:UITextLayoutDirectionRight];
    NSString *tappedLine = [textView textInRange:textRange];
    }

//This is where size of view is changed in response to quantity of text in viewwillappear

CGFloat fixedWidth = myView.frame.size.width;
    //MAXFLOAT IS THE maximum float system allows
    CGSize newSize = [myView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
    CGRect newFrame = myView.frame;
    newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
    myView.frame = newFrame;
 [self.myView sizeToFit];
    self.myView.editable = NO;
    self.myView.scrollEnabled=NO;

Thanks for any suggestions.

Upvotes: 0

Views: 211

Answers (1)

Artem Rizhov
Artem Rizhov

Reputation: 123

I made small test just with your code. For me all works fine. I added timer with change text every 7 seconds for test. After change size I can always tap to any text in the textView with new size. Maybe problem in some additional code ?

My test project xCode 9.2: https://ufile.io/ngo47

#import "ViewController.h"

@interface ViewController ()
{
    IBOutlet UITextView* myView;
    NSTimer* timer;
}

@end

@implementation ViewController

//This is method that handles tap
- (void) handleTap:(UITapGestureRecognizer *)recognizer{
    UITextView *textView =  (UITextView *)recognizer.view;
    CGPoint location = [recognizer locationInView:textView];
    CGPoint position = CGPointMake(location.x, location.y);
    UITextPosition *tapPosition = [textView closestPositionToPoint:position];
    UITextRange *textRange = [textView.tokenizer rangeEnclosingPosition:tapPosition withGranularity:UITextGranularityLine inDirection:UITextLayoutDirectionRight];
    NSString *tappedLine = [textView textInRange:textRange];

    NSLog(@"%@", tappedLine);
}


- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];

    [self resizeView];
}

- (void)resizeView{
    //This is where size of view is changed in response to quantity of text in viewwillappear

    CGFloat fixedWidth = myView.frame.size.width;
    //MAXFLOAT IS THE maximum float system allows
    CGSize newSize = [myView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
    CGRect newFrame = myView.frame;
    newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
    myView.frame = newFrame;
    [self->myView sizeToFit];
    self->myView.editable = NO;
    self->myView.scrollEnabled=NO;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    //This is how the recognizer is created in viewdidload:
    UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc]initWithTarget:self
                                                                            action:@selector(handleTap:)];
    //tapList.cancelsTouchesInView = NO;
    [self->myView addGestureRecognizer:tapRec];

    NSArray* someTexts = @[@"text1, text1, text1, text1, text1, text1, text1, text1, text1, text1",
                           @"text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2, text2",
                           @"text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, text3, ",
                           ];
    static NSInteger textIndex = 0;
    timer = [NSTimer scheduledTimerWithTimeInterval:7.0 repeats:YES block:^(NSTimer * timer){
        self->myView.text = someTexts[textIndex];
        [self resizeView];
        textIndex ++;
        if (textIndex >= someTexts.count) {
            textIndex = 0;
        }
    }];
}

@end

Upvotes: 1

Related Questions