Установите эксклюзивный контакт между UIRepresentableView и представлением SwiftUI

#ios #swiftui #uiviewrepresentable

Вопрос:

У меня была uiviewпредставляемая реализация для UITextView, позволяющая отображать и обрабатывать ссылки на

 ...
struct TextViewWrapper: UIViewRepresentable {
    ....
     func makeUIView(context: Context) -> UITextView {
        let textView = UITextView()
        textView.text = text
        textView.textColor = foregroundColor
        textView.font = font
        textView.backgroundColor = .white
        textView.dataDetectorTypes = .link
        textView.isEditable = false
        textView.isSelectable = true
        textView.isScrollEnabled = false
        textView.delegate = context.coordinator
        textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        textView.isExclusiveTouch = true
        recalculateHeight(view: textView, result: $calculatedHeight)
        return textView
    }
   ....

}

// Coordinator
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
    onSelectLink(URL)
    return false
}
...
 

Это используется в представлении SwiftUI следующим образом:

 struct Content: View {
    var body: some View {
        VStack {
            TextViewWrapper(text: "Text with link https://google.com", onSelectLink: { _ in print("On select link") })
        }
        .onTapGesture { print("On tap gesture") }
    }
}
 

Примечание: Это упрощенный пример. Но проблема в том, что взаимодействие со ссылкой вызывает обратный вызов onSelectLink, но также позволяет выполнять распознаватель onTapGesture. Я ожидаю, что касание UITextView будет иметь приоритет, а onTapGesture будет проигнорировано.

Комментарии:

1. Зачем тогда вам нужен onTapGesture просмотр поверх текста? Просто удалите его из общего VStack и положите только туда, где ожидалось.

2. @Asperi Просто для уточнения, компонент VStack является картой (модификатор крана предназначен для отображения деталей), внутри VStack есть больше просмотров. Я хочу TextViewWrapper , чтобы захватить ссылки (shouldInteractWithLinks: UITextViewDelegate) и избежать срабатывания onTapGesture, но если пользователь нажмет на текст, который не является обнаруженной ссылкой (тогда это может позволить обработать нажатие с помощью карты ~ onTapGesture)

Ответ №1:

Возможное решение состоит в том, чтобы добавить onTapGesture к TextViewWrapper нему и игнорировать его:

 VStack {
    TextViewWrapper(text: "Text with link https://google.com", onSelectLink: { _ in print("On select link") })
        .onTapGesture {
            // ignore this tap
        }
}.onTapGesture {
    print("On tap gesture")
}
 

Комментарии:

1. Спасибо! Это решение, по крайней мере, исправит нажатие на ссылку, предотвращающую запуск жеста карты.