3

I have a string, for example "F (R U R' U') (R U R' U') (R U R' U') F'". I am using NSAttributedString to search for the text in brackets (R U R' U') and replace it with the same text, just in a different colour. The code I'm using is

let mutableAttributedString = NSMutableAttributedString(string: algToShow) 
var searchRange = NSRange(location: 0, length: algToShow.count)
var foundRange1 = NSRange()
foundRange1 = (algToShow as NSString).range(of: "(R U R' U')", options: NSString.CompareOptions.caseInsensitive, range: searchRange)
if foundRange1.location != NSNotFound || foundRange2.location != NSNotFound || foundRange3.location != NSNotFound || foundRange4.location != NSNotFound || foundRange5.location != NSNotFound {
            // found an occurrence of the substring! do stuff here
            searchRange.location = foundRange1.location + foundRange1.length
            mutableAttributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red, range: foundRange1)

However, it only highlights the first set of text/brackets; the others are ignored completely. The question is how can I check for how many times the brackets appear, and replace every instance of them?

Thanks.

Luke B
  • 288
  • 2
  • 5
  • 18
  • 1
    One option would be to use [NSRegularExpression](https://developer.apple.com/documentation/foundation/nsregularexpression) and then enumerate the matches and add the attributes accordingly. – Alladinian May 09 '19 at 16:15
  • Check this https://stackoverflow.com/a/49186871/7250862 – RajeshKumar R May 09 '19 at 16:16
  • Possible duplicate of [How to find Multiple NSRange for a string from full string iOS swift](https://stackoverflow.com/questions/49184837/how-to-find-multiple-nsrange-for-a-string-from-full-string-ios-swift) – RajeshKumar R May 09 '19 at 16:17
  • This is a [repost of your previous question](https://stackoverflow.com/questions/56048433/regular-expression-and-nsattributedstring-to-change-colour-of-all-the-same-words?noredirect=1#comment98748265_56048433) (which you have actually edited based on the duplicate). Why does this reposted question take a step back and not make use of the changes you put in your previous question? As written, this new question will get closed as a duplicate again. – rmaddy May 09 '19 at 16:57
  • That wasn't my post - that's actually the person I'm working with :) – Luke B May 09 '19 at 17:04
  • Ok but this question is still a step back from that one. Why post a new question starting over when you had already made progress? – rmaddy May 09 '19 at 17:33
  • I didn't realise it had been posted. – Luke B May 09 '19 at 17:35

2 Answers2

6

This is the regular expression pattern \((.*?)\) that will find the occurrences within parentheses, please test the pattern

you can use following method and pass above pattern

func regexMatches(_ pattern: String, string: String) throws -> [NSTextCheckingResult]? {
    let regex = try NSRegularExpression(pattern: pattern)
    let range = NSRange(string.startIndex..<string.endIndex, in: string)
    return regex.matches(in: string, options: [], range: range)
}

Usage

let algToShow = "F (R U R' U') (R U R' U') (R U R' U') F'"
let mutableAttributedString = NSMutableAttributedString(string: algToShow)
if let matches = try? regexMatches("\\((.*?)\\)", string: algToShow) {
    for match in matches {
        mutableAttributedString.addAttribute(.foregroundColor, value: UIColor.red, range: match.range)
    }
}
AamirR
  • 11,672
  • 4
  • 59
  • 73
0

I found a way to do it:

I first check for the brackets, never bind what the content is. Once I've done that, I identify more precisely the stringiest. For example:

func regexMatchesToString(_ pattern: String, string: String) throws -> [String]? {
        let regex = try NSRegularExpression(pattern: pattern)
        let range = NSRange(string.startIndex..<string.endIndex, in: string)
        let results = regex.matches(in: string, options: [], range: range)
        return results.map {
            String(string[Range($0.range, in: string)!])
        }
    }
    func regexMatches(_ pattern: String, string: String) throws -> [NSTextCheckingResult]? {
        let regex = try NSRegularExpression(pattern: pattern)
        let range = NSRange(string.startIndex..<string.endIndex, in: string)
        return regex.matches(in: string, options: [], range: range)
    }

    string = algAtCell //The text displayed in my UITableView
    atStr = NSMutableAttributedString(string: string)

if let stringMatches1 = try? regexMatchesToString("\\((.*?)\\)", string: string) {
        for triggerString in stringMatches1 {
            print("String \(string)")
            if triggerString == ("(R U R' U')") {
                let matches = try? regexMatches("\\((R U R' U')\\)", string: string)
                for match in matches! {
                    atStr.addAttribute(.foregroundColor, value: UIColor.init(displayP3Red: 255/255, green: 10/255, blue: 10/255, alpha: 1.0), range: match.range)
                }

Hope this helps if anyone needs it.

Luke B
  • 288
  • 2
  • 5
  • 18