简体   繁体   中英

UITextView with clickable link or phone number and custom attributed string in Swift

I am working on an iOS application. And in my app, I'm showing the details of a product in UITextView . The details may contain phone number, email address or website link. I can make that clickable using UITextViews properties. Also in my UITextView , I want to append 'Terms&Condition' string in the last position, and when clicks on it I want to show the terms and condition in a popup. Thats also I did with NSAttributed String. But the problem is when I click the URL, or phone number or my custom attributed string, it shows the terms pop up. How can I differentiate my clicks, that means if I click the website it should open in the browser or if it is phone number ask me the prompt to call to that number and if it is terms and condition, open the popup. Please help me. I tried all the ways. Is it possible in iOS?
Here is my code for adding

let str = "\(offer_desc) t&c"  //t&c is the clickbale string added to the actaul offer description

let attributedString = NSMutableAttributedString(string: str, attributes: [NSAttributedStringKey.font: UIFont(name: "Avenir-Medium", size: 12)])

let foundRange = attributedString.mutableString.range(of: "t&c") 
attributedString.addAttribute(NSAttributedStringKey.link, value: "", range: foundRange)

descriptionTextView.linkTextAttributes = [NSAttributedStringKey.foregroundColor.rawValue : UIColor.green]

descriptionTextView.attributedText = attributedString


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

    self.showTermsCondition(self)
    return false
}

When I run my application. the link also comes in green color and when clicks open the terms popup.

在此输入图像描述

Firstly you want to do this in one textview? if not you can use stackview and put your textviews into it. So you can do what you what you want via gesture recognizers.

If you wanna do it on one textview, may be you can share a design for solving your problem more clearly.

Yes, I fixed my issue. What we need to do is, check the URL in the UITextView's callback like this.

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
    if URL.absoluteString == ""  { //
       self.showTermsCondition(self)
       return false
    }

    return true //System will take care according to URL type, weblink, email or phone number
}

or you can do this way also,

@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
}

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)

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM