How to make attributed string within a UITextView

2020-04-15 16:01发布

问题:

By default the screen reader will select the entire view, and the link isn't able to be followed on a double tap. In fact, pressing activate on the accessibility inspector crashes the app delegate without any stack trace in the console. I've tried messing with the accessibility traits within the UITextView itself but I didn't have any luck.

let quoteAttributedStr = NSMutableAttributedString(string: "This is a test String" + " ")
                let enableLinkText = NSAttributedString(string: "this is the clickable text", attributes: dummyLinkAttribute)
                quoteAttributedStr.append(enableLinkText)

                return quoteAttributedStr

回答1:

To make a portion of the NSMutableAttributedString selectable, you'll need to set it as a link like so:

quoteAttributedStr.setAsLink("string that you wish to be selectable goes here", linkURL: "url")

You'll also need to add the UITextViewDelegate, and add:

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

to handle it.

Here's an extension for the setAsLink that I forgot to include:

extension NSMutableAttributedString {

public func setAsLink(_ textToFind:String, linkURL:String) -> Bool {

    let foundRange = self.mutableString.range(of: textToFind)
    if foundRange.location != NSNotFound {
        self.addAttribute(NSLinkAttributeName, value: linkURL, range: foundRange)
        return true
    }
    return false
}
}


回答2:

The problem deals with a specific VoiceOver gesture to be used when a link must be activated in a UITextView.

I created a blank project (iOS 12, Xcode 10) including the code snippet hereafter to get 2 URLs in the myTextView element :

class TextViewURLViewController: UIViewController, UITextViewDelegate {

    @IBOutlet weak var myTextView: UITextView!

    let myString = "Follow this developers guide if you already know the VoiceOver gestures."
    let myDevURL = "https://a11y-guidelines.orange.com/mobile_EN/dev-ios.html"
    let myGesturesURL = "https://a11y-guidelines.orange.com/mobile_EN/voiceover.html"


    override func viewDidLoad() {

        let attributedString = NSMutableAttributedString(string: myString)

        attributedString.addAttribute(.link,
                                      value: myDevURL,
                                      range: NSRange(location: 12,
                                                     length: 17))

        attributedString.addAttribute(.link,
                                      value: myGesturesURL,
                                      range: NSRange(location: 52,
                                                     length: 19))

        myTextView.attributedText = attributedString
        myTextView.font = UIFont(name: myTextView.font!.fontName,
                                 size: 25.0)
    }


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

        UIApplication.shared.open(URL, options: [:])
        return false
    }
}

Follow the steps hereunder to activate the link :

  1. Get the rotor links item with the appropriate gesture.
  2. Swipe up or down with one finger to reach the link.
  3. Double tap and hold until the event on step 4.

  1. A kind of popup shows up above the link.
  2. Once the action sheet appears, flick right to get the Open action.
  3. Double tap to open the URL and get the last screen on step 7.

Following the code snippet above, you can make attributed string within a UITextView accessible and open it by double tapping + holding until the popup appears above your link (this is how VoiceOver works).