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.

7
  • 1
    One option would be to use NSRegularExpression and then enumerate the matches and add the attributes accordingly. Commented May 9, 2019 at 16:15
  • Check this stackoverflow.com/a/49186871/7250862 Commented May 9, 2019 at 16:16
  • Possible duplicate of How to find Multiple NSRange for a string from full string iOS swift Commented May 9, 2019 at 16:17
  • This is a repost of your previous question (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. Commented May 9, 2019 at 16:57
  • That wasn't my post - that's actually the person I'm working with :) Commented May 9, 2019 at 17:04

2 Answers 2

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)
    }
}
Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.