Как перехватить клик по ссылке в UITextView?
это возможно, чтобы выполнить пользовательское действие, когда пользователь нажмите автоопределение телефонной линии в UITextView. Пожалуйста, не советуйте использовать UIWebView вместо этого.
и, пожалуйста, не просто повторяйте текст из ссылки на классы apple
- конечно, я его уже читал.
спасибо.
10 ответов:
Обновление: С ios10,
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction;С ios7 и позже
UITextViewесть метод делегата:- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange *NS_DEPRECATED_IOS(7_0, 10_0, "Use textView:shouldInteractWithURL:inRange:forInteractionType: instead");*для перехвата кликов по ссылкам. И это лучший способ сделать это.
на ios6 и ранее хороший способ сделать это путем создания подклассов
UIApplicationи перезапись-(BOOL)openURL:(NSURL *)url@interface MyApplication : UIApplication { } @end @implementation MyApplication -(BOOL)openURL:(NSURL *)url{ if ([self.delegate openURL:url]) return YES; else return [super openURL:url]; } @endвам нужно будет реализовать
openURL:в свой делегат.теперь, чтобы запустите приложение с вашего нового подкласса
UIApplicationнайдите файл main.м в вашем проекте. В этом небольшом файле, который загружает ваше приложение, обычно есть такая строка:int retVal = UIApplicationMain(argc, argv, nil, nil);третий параметр-это имя класса для вашего приложения. Итак, заменив эту строку на:
int retVal = UIApplicationMain(argc, argv, @"MyApplication", nil);это сделал трюк для меня.
в iOS 7 или более поздней версии
вы можете использовать следующий метод делегата UITextView:
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRangeтекстовое представление вызывает этот метод, если пользователь долго жмет на ссылку. Реализация этого метода является необязательной. По умолчанию текстовое представление открывает приложение, ответственное за обработку типа URL, и передает ему URL. Этот метод можно использовать для запуска альтернативного действия, например отображения веб-содержимого по URL-адресу в веб-представлении в текущем приложение.
важно:
ссылки в текстовых представлениях являются интерактивными только в том случае, если текстовое представление выбирается, но не редактируется. То есть, если значение UITextView выбираемое свойство-да, а свойство isEditable-нет.
Swift версия:
стандартный настройка UITextView должен выглядеть что-то вроде этого, не забывайте, что делегат и dataDetectorTypes.
var textView = UITextView(x: 10, y: 10, width: CardWidth - 20, height: placeholderHeight) //This is my custom initializer textView.text = "dsfadsaf www.google.com" textView.selectable = true textView.dataDetectorTypes = UIDataDetectorTypes.Link textView.delegate = self addSubview(textView)после того, как ваш класс заканчивается добавить этот фрагмент:
class myVC: UIViewController { //viewdidload and other stuff here } extension MainCard: UITextViewDelegate { func textView(textView: UITextView, shouldInteractWithURL URL: NSURL, inRange characterRange: NSRange) -> Bool { //Do your stuff over here var webViewController = SVModalWebViewController(URL: URL) view.presentViewController(webViewController, animated: true, completion: nil) return false } }
Для Swift 3
textView.delegate = self extension MyTextView: UITextViewDelegate func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool { GCITracking.sharedInstance.track(externalLink: URL) return true } }или если цель >= IOS 10
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool
С Swift 3 и i0S 10, Самый простой способ взаимодействия с телефонными номерами, URL-адресами или адресами в
UITextViewиспользоватьUIDataDetectorTypes. Код ниже показывает, как отобразить номер телефона вUITextView, Так что пользователь может взаимодействовать с ним.import UIKit class ViewController: UIViewController { // Link this outlet to a UITextView in your Storyboard @IBOutlet weak var textView: UITextView! override func viewDidLoad() { super.viewDidLoad() textView.text = "+33687654321" textView.isUserInteractionEnabled = true // default: true textView.isEditable = false // default: true textView.isSelectable = true // default: true textView.dataDetectorTypes = [.phoneNumber] } }С этим кодом, при нажатии на номер телефона, a
UIAlertControllerпоявится.
в качестве альтернативы, вы можете использовать
NSAttributedString:import UIKit class ViewController: UIViewController { // Link this outlet to a UITextView in your Storyboard @IBOutlet weak var textView: UITextView! override func viewDidLoad() { super.viewDidLoad() let phoneUrl = NSURL(string: "tel:+33687654321")! // "telprompt://+33687654321" also works let attributes = [NSLinkAttributeName: phoneUrl] let attributedString = NSAttributedString(string: "phone number", attributes: attributes) textView.attributedText = attributedString textView.isUserInteractionEnabled = true // default: true textView.isEditable = false // default: true textView.isSelectable = true // default: true } }С этим кодом, когда нажав на строку с атрибутом, a
UIAlertControllerпоявится.
однако, вы можете выполнить некоторые пользовательские действия вместо того, чтобы сделать
UIAlertControllerвсплывающее окно при нажатии на номер телефона. Или вы можете сохранитьUIAlertControllerвсплывающее и проанализировать собственные действия, в то же время.в обоих случаях вам придется сделать свой
UIViewControllerсоответствуютUITextViewDelegateпротокол и реализоватьtextView(_:shouldInteractWith:in:interaction:). Код ниже показывает, как это сделать оно.import UIKit class ViewController: UIViewController, UITextViewDelegate { // Link this outlet to a UITextView in your Storyboard @IBOutlet weak var textView: UITextView! override func viewDidLoad() { super.viewDidLoad() textView.delegate = self textView.text = "+33687654321" textView.isUserInteractionEnabled = true textView.isEditable = false textView.isSelectable = true textView.dataDetectorTypes = [.phoneNumber] } func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { /* perform your own custom actions here */ print(URL) return false // return true if you still want UIAlertController to pop up } }С этим кодом, при нажатии на номер телефона, нет
UIAlertControllerпоявится, и вы вместо этого получите следующую печать в консоли:тел.:+33687654321
У меня есть динамический контент в виде текста , который может содержать ссылку. ShouldInteractWithURL вызывается только тогда, когда пользователь долго нажимает на ссылку, но не вызывает при нажатии ссылки. Пожалуйста, перенаправьте если приятель имеет ссылку на него.
Ниже приведена часть кода sniped.
UITextView *ltextView = [[UITextView alloc] init]; [ltextView setScrollEnabled:YES]; [ltextView setDataDetectorTypes:UIDataDetectorTypeLink]; ltextView.selectable = YES; [ltextView setEditable:NO]; ltextView.userInteractionEnabled = YES; ltextView.delegate = (id)self; ltextView.delaysContentTouches = NO; [self.view addsubview:ltextview]; - (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange{ [self.mActionDelegate userClickedOnImageLinkFromWebview:URL]; NSLog(@"urls is :- %@",URL); return FALSE; }вышеуказанный метод делегата не вызывается при нажатии.
С уважением, Рохит Янкар
Swift 4:
1) создайте следующий класс (подкласс UITextView):
import Foundation protocol QuickDetectLinkTextViewDelegate: class { func tappedLink() } class QuickDetectLinkTextView: UITextView { var linkDetectDelegate: QuickDetectLinkTextViewDelegate? override init(frame: CGRect, textContainer: NSTextContainer?) { super.init(frame: frame, textContainer: textContainer) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let glyphIndex: Int? = layoutManager.glyphIndex(for: point, in: textContainer, fractionOfDistanceThroughGlyph: nil) let index: Int? = layoutManager.characterIndexForGlyph(at: glyphIndex ?? 0) if let characterIndex = index { if characterIndex < textStorage.length { if textStorage.attribute(NSLinkAttributeName, at: characterIndex, effectiveRange: nil) != nil { linkDetectDelegate?.tappedLink() return self } } } return nil } }
2) где бы вы ни настроили свой textview, сделайте это://init, viewDidLoad, etc textView.linkDetectDelegate = self //outlet @IBOutlet weak var textView: QuickDetectLinkTextView! //change ClassName to your class extension ClassName: QuickDetectLinkTextViewDelegate { func tappedLink() { print("Tapped link, do something") } }
Если вы используете раскадровку, убедитесь, что ваш textview выглядит так в правой панели Identity inspector:
Вуаля! Теперь вы получаете ссылку нажмите немедленно, а не когда URL должен взаимодействовать с URL метод
Я не пробовал это сам, но вы можете попробовать реализовать
application:handleOpenURL:метод в делегате приложения-это выглядит как всеopenURLзапрос проходит через этот обратный вызов.
Не уверен, как бы вы перехватили обнаруженный канал передачи данных, или какой тип функции вам нужно запустить. Но вы можете использовать метод Didbeginediting TextField для запуска теста / сканирования через текстовое поле, если вы знаете, что ищете..например, Сравнение текстовых строк, которые встречаются ###-###-#### формат, или начать с " www."чтобы захватить эти поля, но вам нужно будет написать небольшой код, чтобы обнюхать строку textfields, перестроить то, что вам нужно, а затем извлечь его для вашего использование функции. Я не думаю, что это будет так сложно, как только вы сузили именно то, что вы хотели, а затем сфокусировали свой оператор if() на очень конкретном шаблоне соответствия того, что вам нужно.
из couse это означает, что пользователь собирается коснуться текстового поля для того, чтобы активировать didBeginEditing(). Если это не тот тип взаимодействия с пользователем, который вы искали, вы можете просто использовать таймер триггера, который запускается на ViewDidAppear() или другом на основе необходимости и проходит через строку textfields, а затем в конце вы запускаете методы строки textfield, которые вы построили,вы просто выключаете таймер.
application:handleOpenURL:вызывается при открытии другого приложения код приложение, открыв URL-адрес со схемой, которую поддерживает ваше приложение. Он не вызывается, когда ваше приложение начинает открывать URL-адрес.Я думаю, что единственный способ сделать то, что хочет Владимир, это использовать UIWebView вместо UITextView. Сделайте ваш контроллер и вид реализации UIWebViewDelegate, установить UIWebView делегат контроллера представления, и контроллер представления реализации
webView:shouldStartLoadWithRequest:navigationType:открыть[request URL]в представлении, вместо того, чтобы бросить приложение и открытие его в мобильном сафари.

Comments