Вопрос

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

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

Спасибо.

Это было полезно?

Решение

Обновить:От ,

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction;

От и Позже UITextView имеет метод делегирования:

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange *NS_DEPRECATED_IOS(7_0, 10_0, "Use textView:shouldInteractWithURL:inRange:forInteractionType: instead");*

перехватывать переходы по ссылкам.И это лучший способ сделать это.

Для и ранее хорошим способом сделать это было создание подкласса 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.m в вашем проекте.В этом небольшом файле, который загружает ваше приложение, обычно есть такая строка:

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.Вы можете использовать этот метод для запуска альтернативного действия, такого как отображение веб-содержимого по URL-адресу в веб-представлении в текущем приложении.

Важный:

Ссылки в текстовых представлениях являются интерактивными, только если текстовое представление выбирается, но не редактируется.То есть, если значение UITextView выбираемого свойства равно YES, а редактируемого свойства равно NO.

Для 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
    }
}

или, если target >= IOS 10

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

Быстрая версия:

Ваша стандартная настройка UITextView должна выглядеть примерно так, не забудьте о delegate и 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 5 и iOS 12 вы можете использовать один из трех следующих шаблонов для взаимодействия со ссылками в UITextView.


#1.Используя UITextView's dataDetectorTypes собственность.

Самый простой способ взаимодействия с телефонными номерами, URL-адресами или UITextView заключается в использовании dataDetectorTypes собственность.Приведенный ниже пример кода показывает, как это реализовать.С помощью этого кода, когда пользователь нажимает на номер телефона, появляется UIAlertController всплывает.

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let textView = UITextView()
        textView.text = "Phone number: +33687654321"
        textView.isUserInteractionEnabled = true
        textView.isEditable = false
        textView.isSelectable = true
        textView.dataDetectorTypes = [.phoneNumber]
        textView.isScrollEnabled = false

        textView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(textView)
        textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        textView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
    }

}

#2.Используя UITextViewDelegate's textView(_:shouldInteractWith:in:interaction:) способ

Если вы хотите выполнить какое-то пользовательское действие вместо того, чтобы UIAlertController всплывающее окно появляется, когда вы нажимаете на номер телефона во время использования dataDetectorTypes, вы должны сделать свой UIViewController соответствовать UITextViewDelegate протоколировать и внедрить textView(_:shouldInteractWith:in:interaction:).Приведенный ниже код показывает, как это реализовать:

import UIKit

class ViewController: UIViewController, UITextViewDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        let textView = UITextView()
        textView.delegate = self
        textView.text = "Phone number: +33687654321"
        textView.isUserInteractionEnabled = true
        textView.isEditable = false
        textView.isSelectable = true
        textView.dataDetectorTypes = [.phoneNumber]
        textView.isScrollEnabled = false

        textView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(textView)
        textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        textView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
    }

    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        /* perform your own custom actions here */
        print(URL) // prints: "tel:+33687654321"

        return false // return true if you also want UIAlertController to pop up
    }

}

#3.Используя NSAttributedString и NSAttributedString.Key.link

В качестве альтернативы вы можете использовать NSAttributedString и установить URL для его NSAttributedString.Key.link атрибут.Приведенный ниже пример кода показывает возможную его реализацию.С помощью этого кода, когда пользователь нажимает на приписываемую строку, появляется UIAlertController всплывает.

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let attributedString = NSMutableAttributedString(string: "Contact: ")
        let phoneUrl = NSURL(string: "tel:+33687654321")! // "telprompt://+33687654321" also works
        let attributes = [NSAttributedString.Key.link: phoneUrl]
        let phoneAttributedString = NSAttributedString(string: "phone number", attributes: attributes)
        attributedString.append(phoneAttributedString)

        let textView = UITextView()
        textView.attributedText = attributedString
        textView.isUserInteractionEnabled = true
        textView.isEditable = false
        textView.isSelectable = true
        textView.isScrollEnabled = false

        textView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(textView)
        textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        textView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
    }

}

Я сам этого не пробовал, но вы можете попробовать реализовать application:handleOpenURL: метод в вашем приложении delegate - он выглядит как все openURL запрос проходит через этот обратный вызов.

Не уверен, как вы будете перехватывать обнаруженный канал передачи данных или какой тип функции вам нужно запустить.Но вы можете использовать метод didBeginEditing TextField для запуска теста / сканирования через текстовое поле, если вы знаете, что ищете .. например, сравнивая текстовые строки, которые соответствуют ###-###-#### форматируйте или начинайте с "www.", чтобы захватить эти поля, но вам нужно будет написать небольшой код, чтобы просмотреть строку textfields, повторно определить, что вам нужно, а затем извлечь это для использования вашей функцией.Я не думаю, что это было бы так сложно, как только вы точно определили, что именно вам нужно, а затем сфокусировали свои фильтры оператора if () на очень конкретном шаблоне соответствия тому, что вам нужно.

Конечно, это подразумевает, что пользователь собирается коснуться текстового поля, чтобы активировать функцию didBeginEditing().Если это не тот тип взаимодействия с пользователем, который вы искали, вы могли бы просто использовать таймер запуска, который запускается в viewDidAppear() или другом, основанном на необходимости, и выполняется через строку textfields, затем в конце вы запускаете построчные методы textfield, которые вы создали, вы просто выключаете таймер.

application:handleOpenURL: вызывается при открытии другого приложения ваш приложение, открыв URL-адрес со схемой, поддерживаемой вашим приложением.Он не вызывается, когда ваше приложение начинает открывать URL-адрес.

Я думаю, что единственный способ сделать то, что хочет Владимир, - это использовать UIWebView вместо UITextView.Сделайте так, чтобы ваш контроллер представления реализовал UIWebViewDelegate, установите делегат UIWebView для контроллера представления и в контроллере представления реализуйте webView:shouldStartLoadWithRequest:navigationType: чтобы открыть [request URL] в представлении вместо того, чтобы выходить из своего приложения и открывать его в мобильном Safari.

Быстрый 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 выглядит следующим образом в инспекторе идентификации правой панели:
enter image description here



Вуаля!Теперь вы получаете ссылку tap немедленно, а не тогда, когда URL должен взаимодействовать с методом URL

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top