iOS 13.1 Uitextview Delegate Method Shouldinteract Called When Scrolling on Attachment

iOS 13.1 UITextView delegate method shouldInteract called when scrolling on attachment

It looks like textView:shouldInteractWithURL:inRange:interaction: ends up being called 3 times during a normal link press (if you always return YES).

A couple of times to see if the default action can be invoked (assuming that's what canInvokeDefaultAction is about):

  * frame #0: 0x0000000101610038 Engage`::-[BubbleMessageCell textView:shouldInteractWithURL:inRange:interaction:](self=0x00007ff19e999600, _cmd="textView:shouldInteractWithURL:inRange:interaction:", textView=0x00007ff19eaf2000, url="https://9to5mac.com/2019/09/07/imessage-for-business/", characterRange=location=235, length=33, interaction=UITextItemInteractionInvokeDefaultAction) at BubbleMessageCell.mm:623:5
frame #1: 0x00007fff478b2902 UIKitCore`-[UITextView _allowInteraction:forTextInteractableItem:] + 532
frame #2: 0x00007fff46b8ba1c UIKitCore`-[_UITextInteractableItem _allowInteraction:] + 135
frame #3: 0x00007fff46b8b84d UIKitCore`-[_UITextInteractableItem canInvokeDefaultAction] + 97
frame #4: 0x00007fff477f76f7 UIKitCore`-[_UITextSimpleLinkInteraction _canBeginInteractionSessionForLinkAtPoint:asTap:] + 127
frame #5: 0x00007fff477f75c7 UIKitCore`-[_UITextSimpleLinkInteraction interaction_gestureRecognizer:shouldReceiveTouch:] + 217
frame #6: 0x00007fff477f6506 UIKitCore`-[UITextInteraction gestureRecognizer:shouldReceiveTouch:] + 127
frame #7: 0x00007fff47133669 UIKitCore`-[UIGestureRecognizer _delegateShouldReceiveTouch:] + 493
  * frame #0: 0x0000000101610038 Engage`::-[BubbleMessageCell textView:shouldInteractWithURL:inRange:interaction:](self=0x00007ff19e999600, _cmd="textView:shouldInteractWithURL:inRange:interaction:", textView=0x00007ff19eaf2000, url="https://9to5mac.com/2019/09/07/imessage-for-business/", characterRange=location=235, length=33, interaction=UITextItemInteractionInvokeDefaultAction) at BubbleMessageCell.mm:623:5
frame #1: 0x00007fff478b2902 UIKitCore`-[UITextView _allowInteraction:forTextInteractableItem:] + 532
frame #2: 0x00007fff46b8ba1c UIKitCore`-[_UITextInteractableItem _allowInteraction:] + 135
frame #3: 0x00007fff46b8b84d UIKitCore`-[_UITextInteractableItem canInvokeDefaultAction] + 97
frame #4: 0x00007fff477f77fb UIKitCore`-[_UITextSimpleLinkInteraction _beginInteractionSessionForLinkAtPoint:asTap:] + 167
frame #5: 0x00007fff477f74d0 UIKitCore`-[_UITextSimpleLinkInteraction interaction_gestureRecognizerShouldBegin:] + 196
frame #6: 0x00007fff477f62a1 UIKitCore`-[UITextInteraction gestureRecognizerShouldBegin:] + 307
frame #7: 0x00007fff471339b6 UIKitCore`-[UIGestureRecognizer _shouldBegin] + 413

And then finally when the gesture is actually recognized:

  * frame #0: 0x0000000101610038 Engage`::-[BubbleMessageCell textView:shouldInteractWithURL:inRange:interaction:](self=0x00007ff19e999600, _cmd="textView:shouldInteractWithURL:inRange:interaction:", textView=0x00007ff19eaf2000, url="https://9to5mac.com/2019/09/07/imessage-for-business/", characterRange=location=235, length=33, interaction=UITextItemInteractionInvokeDefaultAction) at BubbleMessageCell.mm:623:5
frame #1: 0x00007fff478b2902 UIKitCore`-[UITextView _allowInteraction:forTextInteractableItem:] + 532
frame #2: 0x00007fff46b8ba1c UIKitCore`-[_UITextInteractableItem _allowInteraction:] + 135
frame #3: 0x00007fff46b8b8cc UIKitCore`-[_UITextInteractableItem invokeDefaultAction] + 94
frame #4: 0x00007fff477f6f32 UIKitCore`-[_UITextSimpleLinkInteraction linkTapped:] + 188
frame #5: 0x00007fff4712bbfb UIKitCore`-[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] + 44

When scrolling, only the first call happens.

This is presumably an iOS 13.1 change, where it checks sooner to see if the link can be interacted with. If you want textView:shouldInteractWithURL:inRange:interaction: to have side effects, you only want to do them when the gesture is actually recognized.

What appears to work for us to to check textView.gestureRecognizers and only do the custom actions if a tap gesture was being recognized.

    BOOL recognizedTapGesture = NO;
for (UIGestureRecognizer *recognizer in textView.gestureRecognizers) {
if ([recognizer isKindOfClass:UITapGestureRecognizer.class] && recognizer.state == UIGestureRecognizerStateEnded) {
recognizedTapGesture = YES;
break;
}
}
if (!recognizedTapGesture) {
// Tap gesture is not being recognized, this must be an early
// check when touches begin. Leave the link handling alone.
return YES;
}

// Do custom action here

return NO;

Why observer onKeyboardDisplayed is called before textViewDidBeginEditing

Finally I found a solution here: Keyboard events called before UITextView delegate events

I changed keyboardWillShowNotification

NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardDisplayed(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)

by keyboardDidShowNotification

NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardDisplayed(notification:)), name: UIResponder.keyboardDidShowNotification, object: nil)

And now it works well: my onKeyboardDisplayed function is called after the delegate textViewDidBeginEditing

3D surface Reconstruction algorithm

The technical term for the "contours" you mentioned is "iso-lines".

Given the set of iso-lines you first need to construct a point cloud in 3D (just a collection of points in 3D space). You do that in two stages. first by sampling each iso-line at a uniform intervals, You get 2D points and then you raise the points by the appropriate height.

sampling a line at uniform intervals can be easily done by tracing it wherever it goes. You can know the height of a line by starting from the most outer line and tracing the lines one by one towards the inside, removing each line you trace and and keeping track of how many lines you traced.

Of course you need to know in advance what is the height difference between the lines and what is the height of the most outer line (or any other line which can be used as a reference)

Once you have a 3D point cloud you can use any one of a number of surface reconstruction algorithms. This company for instance makes an application which does that and you can download a command line demo from their site which will work for up to 30,000 points.



Related Topics



Leave a reply



Submit