Как перехватить клик по ссылке в UITextView?



это возможно, чтобы выполнить пользовательское действие, когда пользователь нажмите автоопределение телефонной линии в UITextView. Пожалуйста, не советуйте использовать UIWebView вместо этого.



и, пожалуйста, не просто повторяйте текст из ссылки на классы apple
- конечно, я его уже читал.



спасибо.

663   10  

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:
enter image description here



Вуаля! Теперь вы получаете ссылку нажмите немедленно, а не когда 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

    Ничего не найдено.