iOS 13.1 วิธีการมอบสิทธิ์ UITextView ควรมีการติดต่อทันทีเมื่อเลื่อนตามเอกสารแนบ


15

ฉันใช้UITextViewวิธีผู้ได้รับมอบหมายเพื่อทำงานที่กำหนดเองบางอย่างเช่นการเปิดเบราว์เซอร์ในแอพเมื่อผู้ใช้แตะที่ URL หรือไฟล์แนบ:

func textView(_ textView: UITextView,
                  shouldInteractWith URL: URL,
                  in characterRange: NSRange,
                  interaction: UITextItemInteraction) -> Bool

ใน iOS 13 วิธีการมอบสิทธิ์นี้จะถูกเรียกแม้เมื่อผู้ใช้เพิ่งเลื่อนดู URL ซึ่งไม่คาดคิด พฤติกรรมนี้ยังนำไปใช้กับไฟล์แนบรูปภาพ

วิธีการลบนั้นตอนนี้ถูกเรียกผ่านการโต้ตอบ

* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 6.1 7.1
  * frame #0: 0x0000000104a54c5c ProjectS1`PostListViewController.textView(textView=0x00000001090a4600, URL=Foundation.URL @ 0x000000016b5d1200, characterRange=location=161, length=9, interaction=invokeDefaultAction, self=0x0000000109b03990) at PostListViewController.swift:610:9
    frame #1: 0x0000000104a54d70 ProjectS1`@objc PostListViewController.textView(_:shouldInteractWith:in:interaction:) at <compiler-generated>:0
    frame #2: 0x00000001b3293eec UIKitCore`-[UITextView _allowInteraction:forTextInteractableItem:] + 212
    frame #3: 0x00000001b2602160 UIKitCore`-[_UITextInteractableItem _allowInteraction:] + 140
    frame #4: 0x00000001b2601f68 UIKitCore`-[_UITextInteractableItem canInvokeDefaultAction] + 100
    frame #5: 0x00000001b31dd528 UIKitCore`-[_UITextSimpleLinkInteraction _canBeginInteractionSessionForLinkAtPoint:asTap:] + 136
    frame #6: 0x00000001b31dd3d0 UIKitCore`-[_UITextSimpleLinkInteraction interaction_gestureRecognizer:shouldReceiveTouch:] + 228
    frame #7: 0x00000001b31dc234 UIKitCore`-[UITextInteraction gestureRecognizer:shouldReceiveTouch:] + 144
    frame #8: 0x00000001b2b5f460 UIKitCore`-[UIGestureRecognizer _delegateShouldReceiveTouch:] + 452
    frame #9: 0x00000001b2b5edf4 UIKitCore`-[UIGestureRecognizer _shouldReceiveTouch:forEvent:recognizerView:] + 488
    frame #10: 0x00000001b2ffa630 UIKitCore`__56-[UITouchesEvent _addGestureRecognizersForView:toTouch:]_block_invoke + 332
    frame #11: 0x00000001b2ffa0e4 UIKitCore`__62-[UITouchesEvent _collectGestureRecognizersForView:withBlock:]_block_invoke + 408
    frame #12: 0x00000001b2ff9b58 UIKitCore`-[UITouchesEvent _collectGestureRecognizersForView:withBlock:] + 308
    frame #13: 0x00000001b2ffa4b0 UIKitCore`-[UITouchesEvent _addGestureRecognizersForView:toTouch:] + 164
    frame #14: 0x00000001b2ffa9a8 UIKitCore`-[UITouchesEvent _addTouch:forDelayedDelivery:] + 812
    frame #15: 0x00000001b300bfac UIKitCore`_AddTouchToEventAndDetermineIfNeedsCancel + 196
    frame #16: 0x00000001b300c074 UIKitCore`____updateTouchesWithDigitizerEventAndDetermineIfShouldSend_block_invoke.96 + 136
    frame #17: 0x00000001aef35b20 CoreFoundation`__NSDICTIONARY_IS_CALLING_OUT_TO_A_BLOCK__ + 24
    frame #18: 0x00000001aef360e4 CoreFoundation`____NSDictionaryEnumerate_block_invoke.11 + 56
    frame #19: 0x00000001aef07a10 CoreFoundation`CFBasicHashApply + 144
    frame #20: 0x00000001aef35c80 CoreFoundation`__NSDictionaryEnumerate + 220
    frame #21: 0x00000001b300d560 UIKitCore`__dispatchPreprocessedEventFromEventQueue + 2444
    frame #22: 0x00000001b30107dc UIKitCore`__handleEventQueueInternal + 4928
    frame #23: 0x00000001b3009960 UIKitCore`__handleHIDEventFetcherDrain + 112
    frame #24: 0x00000001aee61260 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
    frame #25: 0x00000001aee611b4 CoreFoundation`__CFRunLoopDoSource0 + 84
    frame #26: 0x00000001aee60920 CoreFoundation`__CFRunLoopDoSources0 + 184
    frame #27: 0x00000001aee5b7ec CoreFoundation`__CFRunLoopRun + 1068
    frame #28: 0x00000001aee5b098 CoreFoundation`CFRunLoopRunSpecific + 480
    frame #29: 0x00000001b8fc5534 GraphicsServices`GSEventRunModal + 108
    frame #30: 0x00000001b2f7b7ac UIKitCore`UIApplicationMain + 1940
    frame #31: 0x0000000104b090d0 ProjectS1`main at AppDelegate.swift:25:7
    frame #32: 0x00000001aecdaf30 libdyld.dylib`start + 4

ดังนั้นคำถามของฉันคือมีวิธีใดที่จะทราบว่าผู้ใช้แตะที่ URL หรือเพียงแค่เลื่อนบน URL หรือไม่


1
นี่เป็นปัญหา "รู้จัก" ใน iOS 13.1 เป็นที่รู้จักกันดีในหมู่นักพัฒนาว่าทวีตและเราหลายคนได้ยื่นรายงานข้อผิดพลาด ตั้งแต่ iOS 13.2 เบต้า seed 1 มันยังไม่ได้รับการแก้ไข รายงานข้อบกพร่องและเลือกวิธีแก้ปัญหา - ขึ้นอยู่กับคุณและขึ้นอยู่กับวิธีการของแอปการทำงาน - คุณสามารถทำอะไรและเพียงแค่รอหรือลองวิธีแก้ปัญหา (เช่นหนึ่งที่อธิบายไว้ในหัวข้อนี้ - twitter.com/scelis/status/ 1176676097754198017 ) สิ่งที่ฉันทำเป็นการส่วนตัวไม่มีอะไรในบางที่และในที่อื่นฉันลบ UITextViewDelegate และปล่อยให้พฤติกรรมเริ่มต้นเข้ามาแทนที่ (เปิดลิงก์ใน Safari)
bpapa

คำตอบ:


15

ดูเหมือนว่าtextView:shouldInteractWithURL:inRange:interaction:จะสิ้นสุดลงด้วยการถูกเรียกว่า 3 ครั้งในระหว่างการกดลิงก์ปกติ (ถ้าคุณมักจะกลับมาYES)

สองสามครั้งเพื่อดูว่าการกระทำเริ่มต้นสามารถเรียกใช้ (สมมติว่าเป็นสิ่งที่canInvokeDefaultActionเกี่ยวกับ):

  * 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

และในที่สุดเมื่อการรับรู้ท่าทางสัมผัสจริง:

  * 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

เมื่อเลื่อนจะมีเพียงสายแรกเท่านั้นที่เกิดขึ้น

นี่น่าจะเป็นการเปลี่ยนแปลง iOS 13.1 ซึ่งจะตรวจสอบเร็วกว่านี้เพื่อดูว่าลิงก์สามารถโต้ตอบได้หรือไม่ หากคุณต้องการtextView:shouldInteractWithURL:inRange:interaction:มีผลข้างเคียงคุณจะต้องทำสิ่งเหล่านั้นเมื่อท่าทางสัมผัสได้รับการยอมรับ

สิ่งที่ดูเหมือนจะใช้ได้สำหรับเราที่จะตรวจสอบtextView.gestureRecognizersและดำเนินการตามที่กำหนดเองเฉพาะเมื่อมีการจดจำท่าทางสัมผัส

    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;

1
ขอบคุณ! โซลูชันของคุณใช้งานได้ดีบนลิงก์ สิ่งที่แนบมากับภาพ? การเลื่อนหรือแตะที่ไฟล์แนบของภาพมีสแต็คการโทรเดียวกันและตรวจสอบสถานะตัวจำแนกท่าทางไม่ทำงานกับไฟล์แนบ
kukushi

5

ฉันเพิ่งพบปัญหาที่น่าผิดหวังเหมือนกันใน iOS 13 นี่คือการแก้ไขที่ได้ผลสำหรับฉันใน Swift ที่ได้แรงบันดาลใจจากคำตอบของ Mihai ด้านบน

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {

    switch interaction {
    case .invokeDefaultAction:
        if textView.gestureRecognizers?.contains(where: {$0.isKind(of: UITapGestureRecognizer.self) && $0.state == .ended}) == true {

            // Handle your custom logic here.

            return false
        }
        return true
    case .presentActions:

        // Default action.

        return true
    case .preview:

        // Default action.

        return true
    @unknown default:
        fatalError()
    }
}

สิ่งนี้ใช้ไม่ได้กับ iPad แก้ไขด้วยการแนบ UITapGestureRecognizer อื่น
ccoroom
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.