Christian Fox
Christian Fox

Reputation: 400

Setting a UITextView exclusion path dynamically while scrolling up causes an infinite loop

I have a UITextView in a UIViewController. In front of that UITextView is another UIViewController containing two buttons. The two buttons are static and they obscure the text in the text view.

What I am trying to achieve is an exclusion path on the text that wraps around where the two buttons are and when the text view is scrolled the exclusion path is recalculated so the text is always 100% visible. To do this I set the initial exclusion path in -viewWillAppear and then use -scrollViewDidScroll: and scrollView.contentOffset to recalculate the exclusion path.

This all works fine while scrolling down however once I start scrolling back up I get stuck in a loop and the processor maxes out.

If I log at -scrollViewDidScroll: I get this:

content offset = {0, 932}
content offset = {0, 584}
content offset = {0, 932}
content offset = {0, 584}
content offset = {0, 932}
content offset = {0, 584}
etc

So as the scrollView scrolls up, it recalculates the exclusion path which pushes the text down and pushes the scrollView down... I think that is what is happening. Although 350pxs seems a big difference when it is just a word or two that gets moved onto the next line.

My question is then, why is this happening and what can I do to fix it?

Here is the code:

-(void)viewWillAppear:(BOOL)animated{
   [super viewWillAppear:animated];
   [self updateExclusionPathWithYOffset:0.0f
                                  width:30.0f];
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
   NSLog(@"content offset =  %@",NSStringFromCGPoint(scrollView.contentOffset));
   [self updateExclusionPathWithYOffset:scrollView.contentOffset.y
                                  width:30.0f];
}

 -(void)updateExclusionPathWithYOffset:(CGFloat)yOffset width:(CGFloat)width{
   CGRect rect = CGRectMake(self.textView.bounds.size.width -width,
                         -10.0f + yOffset,
                         width,
                         105.0f);
   UIBezierPath *path = [UIBezierPath bezierPathWithRect:rect];
   [[self.textView textContainer]setExclusionPaths:@[path]];
 }

** Edit ** It seems I was missing the obvious. -updateExclusionPathWithYOffset: width: changes the textView layout which causes -scrollViewDidScroll: to fire which is what causes the loop.

I'm still interested in a way to avoid this. Thanks in advance for anyone that will take the time.

Upvotes: 3

Views: 535

Answers (1)

Mof
Mof

Reputation: 363

Was struggling with this as well. The way I did it was to add my exclusion path/s in UITextViewTextDidChangeNotification listener:

  [[NSNotificationCenter defaultCenter] addObserver:self
                                       selector:@selector(didReceiveTextViewNotification:)
                                           name:UITextViewTextDidChangeNotification
                                         object:self];

Upvotes: 0

Related Questions