it-swarm.com.de

UITextView mit Hyperlink-Text

Mit einem nicht bearbeitbaren UITextView möchte ich Text wie folgt in iOS9 + einbetten:

Einfach hier klicken um sich zu registrieren

Ich kann eine Funktion erstellen und den Text bearbeiten, aber gibt es einen einfacheren Weg? 

Ich sehe, dass ich NSTextCheckingTypeLink verwenden kann, so dass der Text ohne den "Klicken hier" -Teil anklickbar ist.

Einfach http://example.com um sich zu registrieren

Ich verwende Xcode 8 und Swift 3, wenn dies relevant ist.

19
Adam Nelson

Set isEditable = false oder die Textansicht wechselt in den Textbearbeitungsmodus, wenn der Benutzer darauf tippt. 

Swift 4 und später

let attributedString = NSMutableAttributedString(string: "Just click here to register")
let url = URL(string: "https://www.Apple.com")!

// Set the 'click here' substring to be the link
attributedString.setAttributes([.link: url], range: NSMakeRange(5, 10))

self.textView.attributedText = attributedString
self.textView.isUserInteractionEnabled = true
self.textView.isEditable = false

// Set how links should appear: blue and underlined
self.textView.linkTextAttributes = [
    .foregroundColor: UIColor.blue,
    .underlineStyle: NSUnderlineStyle.single.rawValue
]
34
Code Different

Die gleiche Lösung für Swift 3 mit Erweiterungen: 

A. Erweiterung hinzufügen -

extension UITextView {
    func hyperLink(originalText: String, hyperLink: String, urlString: String) {
        let style = NSMutableParagraphStyle()
        style.alignment = .center
        let attributedOriginalText = NSMutableAttributedString(string: originalText)
        let linkRange = attributedOriginalText.mutableString.range(of: hyperLink)
        let fullRange = NSMakeRange(0, attributedOriginalText.length)
        attributedOriginalText.addAttribute(NSLinkAttributeName, value: urlString, range: linkRange)
        attributedOriginalText.addAttribute(NSParagraphStyleAttributeName, value: style, range: fullRange)
        attributedOriginalText.addAttribute(NSFontAttributeName, value: UIFont.systemFont(ofSize: 10), range: fullRange)
        self.linkTextAttributes = [
            NSForegroundColorAttributeName: UIConfig.primaryColour,
            NSUnderlineStyleAttributeName: NSUnderlineStyle.styleSingle.rawValue,
        ]
        self.attributedText = attributedOriginalText
    }
}

B. Link-URL hinzufügen - let linkUrl = "https://www.my_website.com"

C. Implementieren Sie UITextViewDelegate so in Ihrem ViewController -

 class MyViewController: UIViewController, UITextViewDelegate { 
 }

D. Delegatmethode hinzufügen, um Abgriffsereignisse zu behandeln - 

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
    if (URL.absoluteString == linkUrl) {
        UIApplication.shared.openURL(URL)
    }
    return false
    }
}

E. Und zum Schluss noch Dinge, die Sie für Ihre UITextView unter dem Attributinspektor beachten sollten:

  1. Verhalten - Editable ist auf OFF und Selectable auf ON gestellt.
  2. Datendetektoren - Link ist eingeschaltet.

Verwendungszweck - 

textView.hyperLink(originalText: "To find out more please visit our website", hyperLink: "website", urlString: linkUrl)

Cheers & Happy Coding!

4
Tejas

Swift 4 Code. Vielleicht bin ich der einzige, der mehrere Links setzen und die Wörter in einer Nachricht einfärben muss. Ich habe eine AttribTextHolder-Klasse erstellt, um alle Informationen zu Text in diesem Halter zu sammeln und sie einfach zwischen Objekten zu übertragen, um Text irgendwo tief in einem Controller auf UITextView zu setzen.

class AttribTextHolder {

        enum AttrType {
            case link
            case color
        }

        let originalText: String
        var attributes: [(text: String, type: AttrType, value: Any)]


        init(text: String, attrs: [(text: String, type: AttrType, value: Any)] = [])
        {
            originalText = text
            attributes = attrs
        }

        func addAttr(_ attr: (text: String, type: AttrType, value: Any)) -> AttribTextHolder {
            attributes.append(attr)
            return self
        }

        func setTo(textView: UITextView)
        {
            let style = NSMutableParagraphStyle()
            style.alignment = .left

            let attributedOriginalText = NSMutableAttributedString(string: originalText)

            for item in attributes {
                let arange = attributedOriginalText.mutableString.range(of: item.text)
                switch item.type {
                case .link:
                    attributedOriginalText.addAttribute(NSAttributedString.Key.link, value: item.value, range: arange)
                case .color:
                    var color = UIColor.black
                    if let c = item.value as? UIColor { color = c }
                    else if let s = item.value as? String { color = s.color() }
                    attributedOriginalText.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: arange)
                default:
                    break
                }
            }

            let fullRange = NSMakeRange(0, attributedOriginalText.length)
            attributedOriginalText.addAttribute(NSAttributedString.Key.paragraphStyle, value: style, range: fullRange)

            textView.linkTextAttributes = [
                kCTForegroundColorAttributeName: UIColor.blue,
                kCTUnderlineStyleAttributeName: NSUnderlineStyle.styleSingle.rawValue,
            ] as [String : Any]

            textView.attributedText = attributedOriginalText
        }
 }

Benutze es so:

 let txt = AttribTextHolder(text: "To find out more visit our website or email us your questions")
            .addAttr((text: "our website", type: .link, "http://example.com"))
            .addAttr((text: "our website", type: .color, "#33BB22"))
            .addAttr((text: "email us", type: .link, "mailto:[email protected]"))
            .addAttr((text: "email us", type: .color, UIColor.red))
 ....
 ....
 txt.setTo(textView: myUITextView)

Auch in diesem Code verwende ich eine einfache String-Erweiterung, um String-Hex-Werte in UIColor-Objekte zu konvertieren

extension String {
/// Converts string color (ex: #23FF33) into UIColor
func color() -> UIColor {
    let hex = self.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
    var int = UInt32()
    Scanner(string: hex).scanHexInt32(&int)
    let a, r, g, b: UInt32
    switch hex.characters.count {
    case 3: // RGB (12-bit)
        (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
    case 6: // RGB (24-bit)
        (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
    case 8: // ARGB (32-bit)
        (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
    default:
        (a, r, g, b) = (255, 0, 0, 0)
    }
    return UIColor(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255)
  }
}
2

Die gleiche Lösung für Swift 4 mit Erweiterungen:

extension UITextView {


    func hyperLink(originalText: String, hyperLink: String, urlString: String) {

            let style = NSMutableParagraphStyle()
            style.alignment = .left

            let attributedOriginalText = NSMutableAttributedString(string: originalText)
            let linkRange = attributedOriginalText.mutableString.range(of: hyperLink)
            let fullRange = NSMakeRange(0, attributedOriginalText.length)
            attributedOriginalText.addAttribute(NSAttributedStringKey.link, value: urlString, range: linkRange)
            attributedOriginalText.addAttribute(NSAttributedStringKey.paragraphStyle, value: style, range: fullRange)
            attributedOriginalText.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.blue, range: fullRange)
            attributedOriginalText.addAttribute(NSAttributedStringKey.font, value: UIFont.systemFont(ofSize: 10), range: fullRange)

            self.linkTextAttributes = [
               kCTForegroundColorAttributeName: UIColor.blue,
               kCTUnderlineStyleAttributeName: NSUnderlineStyle.styleSingle.rawValue,
            ] as [String : Any]


            self.attributedText = attributedOriginalText
        }

}
2
Chetan Dobariya

Swift 5 Dies basiert auf Tejas 'Antwort, da einige Gegenstände in beiden Klassen veraltet waren.

extension UITextView {


func hyperLink(originalText: String, hyperLink: String, urlString: String) {

    let style = NSMutableParagraphStyle()
    style.alignment = .left

    let attributedOriginalText = NSMutableAttributedString(string: originalText)
    let linkRange = attributedOriginalText.mutableString.range(of: hyperLink)
    let fullRange = NSMakeRange(0, attributedOriginalText.length)
    attributedOriginalText.addAttribute(NSAttributedString.Key.link, value: urlString, range: linkRange)
    attributedOriginalText.addAttribute(NSAttributedString.Key.paragraphStyle, value: style, range: fullRange)
    attributedOriginalText.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.blue, range: fullRange)
    attributedOriginalText.addAttribute(NSAttributedString.Key.font, value: UIFont.systemFont(ofSize: 10), range: fullRange)

    self.linkTextAttributes = [
        kCTForegroundColorAttributeName: UIColor.blue,
        kCTUnderlineStyleAttributeName: NSUnderlineStyle.single.rawValue,
        ] as [NSAttributedString.Key : Any]

    self.attributedText = attributedOriginalText
}

Vergessen Sie nicht, UITextViewDelegate zu Ihrem View Controller hinzuzufügen und let linkUrl = " https://example.com " festzulegen.

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
    if (URL.absoluteString == linkUrl) {
        UIApplication.shared.open(URL) { (Bool) in

        }
    }
    return false
}

Verwendung bleibt gleich:

textView.hyperLink(originalText: "To find out more please visit our website", hyperLink: "website", urlString: linkUrl)
1
elarcoiris

Sie können diese einfache Methode verwenden, um einen Hyperlink zu jeder Zeichengruppe hinzuzufügen, die mit tag beginnt

func addLink(forString string : NSMutableAttributedString
        ,baseURL : String
        ,tag : String){
        let array = string.string.replacingOccurrences(of: "\n", with: " ").components(separatedBy: " ")
        let filterArray = array.filter { (string) -> Bool in
            return string.contains(tag)
        }
        for element in filterArray {
            let removedHashtag = element.replacingOccurrences(of: tag, with: "")
            let url = baseURL + removedHashtag
            let range = NSString.init(string: (string.string)).range(of: element)
            string.addAttributes([NSAttributedStringKey.link : url.replacingOccurrences(of: " ", with: "")], range: range)
        }
    }
0
Apoorv Suri