WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

How to differentiate between two identically spelled words in UITextView?

Forums > iOS

In my storybook app, I have pages of static (uneditable) text that I display in a UITextView. Users can tap on any word to get more info about the word. I maintain a list of word information for all of the words in the app.

Currently, the word info lookup is accomplished with this method adapted from SO:

var textView = UITextView()

override func viewDidLoad() {
        let tap = UITapGestureRecognizer(target: self, action: #selector(tapResponse(recognizer:)))

        textView.addGestureRecognizer(tap)
        }

 @objc func tapResponse(recognizer: UITapGestureRecognizer) {
        let location: CGPoint = recognizer.location(in: textView)
        let position: CGPoint = CGPoint(x: location.x, y: location.y)
        let tapPosition: UITextPosition = textView.closestPosition(to: position)!
        guard let wordRange: UITextRange = textView.tokenizer.rangeEnclosingPosition(tapPosition, with: UITextGranularity.word, inDirection: UITextDirection(rawValue: 1)) else {return}

        var tappedWord: String = textView.text(in: wordRange) ?? ""

        // safely unwrap the word to make sure it's currently in our list of words
        if let word = Word.returnWord(tappedWord) {
            delegate?.wordSelected(word: word)
        }

Unfortunately, this isn't able to distinguish between two identically spelled but different words. For example: "She read everything there was to read." "Read" is used with two different tenses and pronounced two different ways, but my currently approach wouldn't be able to distinguish between them.

Conceptually, two approaches spring to mind, but I don't know a) if either are good, or b) how to accomplish either :/

Approach #1:

  • since the text in the app is static, for each chunk of text, maintain a list of ranges where an alternative lookup should be performed.

Relying on specific ranges seems error prone because there are both starting and ending values that could get messed up. Would also be a more complicated object to create / store.

Approach #2:

  • Enumerate the words in the text. Rather than use a range to look up a word, figure out what the index of the tapped word is. Maintain a list of indexes for each chunk of text and perform alternative lookups based on that.

This approach seems more complicated to implement, but easier to maintain. I have greater faith in my ability to specify indexes vs text ranges when it comes to doing lookups. Unlike approach one, rather than a custom object, this could probably be implemented with a dictionary.

Any advice on how to accomplish approach 1 or 2, or something even better?

1      

Hacking with Swift is sponsored by RevenueCat

SPONSORED In-app subscriptions are a pain. The code can be hard to write, hard to test, and full of edge cases. RevenueCat makes it straightforward and reliable so you can get back to building your app.

Explore the docs

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.