How to make UITextView detect links for website, mail and phone number
Solution 1:
If you are using OS3.0
you can do it like the following
textview.editable = NO;
textview.dataDetectorTypes = UIDataDetectorTypeAll;
Solution 2:
A note on detecting email addresses: The Mail app must be installed (it's not on the iOS Simulator) for email links to open a message compose screen.
Solution 3:
Swift 3.0 +
As of swift 3.0, use the following code if you want to do it programmatically.
textview.isEditable = false
textview.dataDetectorTypes = .all
Or if you have a storyboard
Solution 4:
Though the Question is super Old. Still if anyone faces the same issue,
Also it can be used as a UILabel. Though Below solution will do the job : [There isn't a need for any library..]
So I've used MFMailcomposer() and UITexView [ Code is in Swift 3.0 - Xcode 8.3.2 ]
A 100% Crash Proof and Working Code Handles all the corner cases. =D
Step 1.
import MessageUI
Step 2. Add the delegate
class ViewController: UITextViewDelegate, MFMailComposeViewControllerDelegate{
Step 3. Add the textView IBOutlet From StoryBoard
@IBOutlet weak var infoTextView: UITextView!
Step 4. Call the below method in your 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
}
Step 5. Implement delegate methods for 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
}
Step 6. Write the helper Methods to open MailComposer and Call App
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)
}
Step 7. Write MFMailComposer's Delegate Method
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)
}
That's it you're Done... =D
Here is the swift file for the above code : textViewWithEmailAndPhone.swift
Set the below properties to Use it as a UILabel