Search code examples
swiftmacosnsstringnstextfield

How to use NSStringEnumerationOptions.ByWords with punctuation


I'm using this code to find the NSRange and text content of the string contents of a NSTextField.

    nstext.enumerateSubstringsInRange(NSMakeRange(0, nstext.length),
        options: NSStringEnumerationOptions.ByWords, usingBlock: {
            (substring, substringRange, _, _) -> () in
            //Do something with substring and substringRange
    }

The problem is that NSStringEnumerationOptions.ByWords ignores punctuation, so that

Stop clubbing, baby seals

becomes

"Stop" "clubbing" "baby" "seals"

not

"Stop" "clubbing," "baby" "seals

If all else fails I could just check the characters before or after a given word and see if they are on the exempted list (where would I find which characters .ByWords exempts?); but there must be a more elegant solution.

How can I find the NSRanges of a set of words, from a string which includes the punctuation as part of the word?


Solution

  • Inspired by Richa's answer, I used componentsSeparatedByString(" "). I had to add a bit of code to make it work for me, since I wanted the NSRanges from the output. I also wanted it to still work if there were two instances of the same word - e.g. 'please please stop clubbing, baby seals'.

    Here's what I did:

                var words:  [String]    = []
                var ranges: [NSRange]   = []
    
                //nstext is a String I converted to a NSString
                words  = nstext.componentsSeparatedByString(" ")
    
                //apologies for the poor naming
                var nstextLessWordsWeHaveRangesFor = nstext
    
                for word in words
                {
                    let range:NSRange = nstextLessWordsWeHaveRangesFor.rangeOfString(word)
                    ranges.append(range)
    
                    //create a string the same length as word so that the 'ranges' don't change in the future (if I just replace it with "" then the future ranges will be wrong after removing the substring)
                    var fillerString:String = ""
    
                    for var i=0;i<word.characters.count;++i{
                       fillerString = fillerString.stringByAppendingString(" ")
                    }
    
                    nstextLessWordsWeHaveRangesFor = nstextLessWordsWeHaveRangesFor.stringByReplacingCharactersInRange(range, withString: fillerString)
                }