Как заставить UITextView обнаруживать ссылки для веб-сайта, почты и номера телефона

У меня есть объект UITextView. В тексте в UIView есть номер телефона, почтовая ссылка, ссылка на сайт. Я хочу показать их в виде ссылок со следующей функциональностью.

Когда кто-то нажимает на URL-адрес - Safari должен открыть веб-сайт. Когда кто-то нажимает на ссылку электронной почты - Почта должна открываться с моим адресом в поле Кому Когда кто-то нажимает на номер телефона - Телефонное приложение должно вызывать этот номер

Кто-нибудь делал это раньше или знает, как с этим справиться?

Спасибо, AJ


person AJ.    schedule 15.06.2009    source источник


Ответы (7)


Если вы используете OS3.0

вы можете сделать это следующим образом

textview.editable = NO;
textview.dataDetectorTypes = UIDataDetectorTypeAll;
person Community    schedule 09.08.2009
comment
В XCode 4 вы можете установить типы обнаружения в IB. - person Oded Ben Dov; 16.08.2011
comment
textview.selectable = ДА; требуется, чтобы ссылка выполняла какие-либо действия, если вы нажмете на нее, по крайней мере, с iOS 7. - person prewett; 31.07.2015
comment
Почему .editable = NO, отключает текстовое поле для редактирования содержимого. - person Raj Aggrawal; 21.07.2016
comment
Есть ли для этого альтернатива Java / Android? - person Nizamudeen Sherif; 06.03.2020

Примечание об обнаружении адресов электронной почты: приложение Mail должно быть установлено (его нет в iOS Simulator), чтобы ссылки электронной почты открывали экран создания сообщения.

person Andrew Hershberger    schedule 18.11.2011
comment
а как насчет случая, когда был выбран сторонний почтовый клиент уровня iOS? - person Blazej SLEBODA; 03.02.2021

Swift 3.0 +

Начиная с swift 3.0, используйте следующий код, если вы хотите сделать это программно.

textview.isEditable = false
textview.dataDetectorTypes = .all

Или если у вас есть раскадровка

введите описание изображения здесь

person Fangming    schedule 25.09.2017

Хотя Вопрос супер Старый. Тем не менее, если кто-то сталкивается с той же проблемой,

Также его можно использовать как UILabel. Хотя решение ниже выполнит свою работу: [Нет необходимости в какой-либо библиотеке ..]

Итак, я использовал MFMailcomposer () и UITexView [Код в Swift 3.0 - Xcode 8.3.2]

100% отказоустойчивый и рабочий код справляется со всеми остальными случаями. = D

Шаг 1.

import MessageUI

Шаг 2. Добавьте делегата

class ViewController: UITextViewDelegate, MFMailComposeViewControllerDelegate{

Шаг 3. Добавьте IBOutlet textView с StoryBoard.

@IBOutlet weak var infoTextView: UITextView!

Шаг 4. Вызовите указанный ниже метод в своем viewDidload ().

func addInfoToTextView()  {
    let attributedString = NSMutableAttributedString(string: "For further info call us on : \(phoneNumber)\nor mail us at : \(email)")
    attributedString.addAttribute(NSLinkAttributeName, value: "tel://", range: NSRange(location: 30, length: 10))
    attributedString.addAttribute(NSLinkAttributeName, value: "mailto:", range: NSRange(location: 57, length: 18))
    self.infoTextView.attributedText = attributedString
    self.infoTextView.linkTextAttributes = [NSForegroundColorAttributeName:UIColor.blue, NSUnderlineStyleAttributeName:NSNumber(value: 0)]
    self.infoTextView.textColor = .white
    self.infoTextView.textAlignment = .center
    self.infoTextView.isEditable = false
    self.infoTextView.dataDetectorTypes = UIDataDetectorTypes.all
    self.infoTextView.delegate = self
}

Шаг 5. Реализуйте методы делегирования для TextView.

@available(iOS, deprecated: 10.0)
func textView(_ textView: UITextView, shouldInteractWith url: URL, in characterRange: NSRange) -> Bool {
    if (url.scheme?.contains("mailto"))! && characterRange.location > 55{
        openMFMail()
    }
    if (url.scheme?.contains("tel"))! && (characterRange.location > 29 && characterRange.location < 39){
        callNumber()
    }
    return false
}

//For iOS 10
@available(iOS 10.0, *)
func textView(_ textView: UITextView, shouldInteractWith url: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
    if (url.scheme?.contains("mailto"))! && characterRange.location > 55{
        openMFMail()
    }
    if (url.scheme?.contains("tel"))! && (characterRange.location > 29 && characterRange.location < 39){
        callNumber()
    }
    return false
}

Шаг 6. Напишите вспомогательные методы для открытия MailComposer и приложения "Позвонить".

func callNumber() {
    if let phoneCallURL = URL(string: "tel://\(phoneNumber)")
    {
        let application:UIApplication = UIApplication.shared
        if (application.canOpenURL(phoneCallURL))
        {
            let alert = UIAlertController(title: "Call", message: "\(phoneNumber)", preferredStyle: UIAlertControllerStyle.alert)
            if #available(iOS 10.0, *)
            {
                alert.addAction(UIAlertAction(title: "Call", style: .cancel, handler: { (UIAlertAction) in
                    application.open(phoneCallURL, options: [:], completionHandler: nil)
                }))
            }
            else
            {
                alert.addAction(UIAlertAction(title: "Call", style: .cancel, handler: { (UIAlertAction) in
                    application.openURL(phoneCallURL)
                }))
            }

            alert.addAction(UIAlertAction(title: "cancel", style: .default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }
    }
    else
    {
        self.showAlert("Couldn't", message: "Call, cannot open Phone Screen")
    }
}
func openMFMail(){
    let mailComposer = MFMailComposeViewController()
    mailComposer.mailComposeDelegate = self
    mailComposer.setToRecipients(["\(email)"])
    mailComposer.setSubject("Subject..")
    mailComposer.setMessageBody("Please share your problem.", isHTML: false)
    present(mailComposer, animated: true, completion: nil)

}

Шаг 7. Напишите метод делегирования MFMailComposer

func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
    switch result {
    case .cancelled:
        print("Mail cancelled")
    case .saved:
        print("Mail saved")
    case .sent:
        print("Mail sent")
    case .failed:
        print("Mail sent failure: \(String(describing: error?.localizedDescription))")
    default:
        break
    }
    controller.dismiss(animated: true, completion: nil)
}

Готово ... = D

Вот быстрый файл для указанного выше кода: textViewWithEmailAndPhone.swift

Задайте следующие свойства, чтобы использовать его как UILabel

Вот изображение для этого ...

person Yash Bedi    schedule 14.09.2017
comment
self.showAlert () - это не что иное, как метод, написанный в другом классе, чтобы показать UIAlertController с заголовком и сообщением. - person Yash Bedi; 14.09.2017
comment
Отказ от ответственности: не тестируйте приложение на симуляторе. Это может привести к сбою.! Работает как шарм на устройстве. - person Yash Bedi; 14.09.2017

Шаг 1. Создайте подкласс UITextview и переопределите функцию canBecomeFirstResponder

Код KDTextView.h:

@interface KDTextView : UITextView

@end

Код KDTextView.m:

#import "KDTextView.h"

// Textview to disable the selection options

@implementation KDTextView

- (BOOL)canBecomeFirstResponder {
    return NO;
}

@end

Шаг 2. Создайте Textview с помощью подкласса KDTextView

KDTextView*_textView = [[KDTextView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    [_textView setScrollEnabled:false];
    [_textView setEditable:false];
    _textView.delegate = self;
    [_textView setDataDetectorTypes:UIDataDetectorTypeAll];
    _textView.selectable = YES;
    _textView.delaysContentTouches = NO;
    _textView.userInteractionEnabled = YES;
    [self.view addSubview:_textView];

Шаг 3. Реализуйте метод делегата

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
{
    return true;
}
person Kuldeep Singh    schedule 10.06.2016
comment
Получил некоторую идею из вашего ответа. Моя проблема решена путем создания подкласса UITextView и переопределения var canBecomeFirstResponder: Bool {return false}. Спасибо за ответ. @ Kuldeep-singh - person Syed Sadrul Ullah Sahad; 19.02.2020

Мне любопытно, у вас есть контроль над отображаемым текстом? Если это так, вам, вероятно, следует просто вставить его в UIWebView и добавить туда несколько ссылок, чтобы сделать это «правильным способом».

person Ed Marty    schedule 15.06.2009
comment
Есть свойство (в SDK 3.0) dataDetectorTypes для UITextView. Что делает работу по обнаружению ссылок в тексте. Но я не могу понять, как его использовать. Для версий до 3.0 я использовал UIButton и сделал их похожими на ссылки. В этом событии касания я вызываю метод, который имеет объект NSURL для веб-сайта. Используя mailto: ‹адрес электронной почты здесь›, вы откроете письмо в приложении Mail. Используя Tel: ‹номер телефона здесь›, можно позвонить по этому номеру. Но это работа. Даже после того, как потратили 2 часа, все еще не удалось понять, как заставить UITextView обрабатывать этих парней. - person AJ.; 15.06.2009

Swift 4.2 Xcode 10.1

func setupContactUsTextView() {
        let text = NSMutableAttributedString(string: "Love your App, but need more help? Text, Call (123) 456-1234 or email ")
        if let font = UIFont(name: "Calibri", size: 17) {
            text.addAttribute(NSAttributedStringKey.font,
                              value: font,
                              range: NSRange(location: 0, length: text.length))
        } else {
            text.addAttribute(NSAttributedStringKey.font,
                              value: UIFont.systemFont(ofSize: 17),
                              range: NSRange(location: 0, length: text.length))
        }
        text.addAttribute(NSAttributedStringKey.foregroundColor,
                          value: UIColor.init(red: 112/255, green: 112/255, blue: 112/255, alpha: 1.0),
                          range: NSRange(location: 0, length: text.length))
        text.addAttribute(NSAttributedStringKey.link, value: "tel://", range: NSRange(location: 49, length: 15))
        let interactableText = NSMutableAttributedString(string: "[email protected]")
        if let font = UIFont(name: "Calibri", size: 17) {
            interactableText.addAttribute(NSAttributedStringKey.font,
                                          value: font,
                                          range: NSRange(location: 0, length: interactableText.length))
        } else {
            interactableText.addAttribute(NSAttributedStringKey.font,
                                          value: UIFont.systemFont(ofSize: 17),
                                          range: NSRange(location: 0, length: interactableText.length))
        }
        interactableText.addAttribute(NSAttributedStringKey.link,
                                      value: "[email protected]",
                                      range: NSRange(location: 0, length: interactableText.length))
        interactableText.addAttribute(NSAttributedStringKey.underlineStyle,
                                      value: NSUnderlineStyle.styleSingle.rawValue,
                                      range: NSRange(location: 0, length: interactableText.length))
        text.append(interactableText)
        videoDescTextView.attributedText = text
        videoDescTextView.textAlignment = .center
        videoDescTextView.isEditable = false
        videoDescTextView.isSelectable = true
        videoDescTextView.delegate = self
    }

    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
        if (characterRange.location > 48 && characterRange.location < 65){
            print("open phone")
        }else{
            print("open gmail")
        }
        return false
    }

Шаги - 1. Установите делегата в текстовое поле и не забудьте реализовать UITextViewDelegate 2. Возьмите выход textView - @IBOutlet weak var videoDescTextView: UITextView! 3. Добавьте эти две функции, указанные выше. Эта функция показывает, как определять номера телефонов, электронную почту из textView, как подчеркивать свой идентификатор электронной почты, как задать собственный цвет вашему тексту, настраиваемый шрифт, как вызвать функцию при нажатии на телефон или электронную почту и т. Д.

Надеюсь, это поможет кому-то сэкономить свое драгоценное время. Удачного кодирования :)

person Prashant Gaikwad    schedule 22.04.2020