Search code examples
swiftstringnsattributedstring

How to use replacingOccurrences for NSAttributedString in swift?


In a NSAttributed type statement, I want to keep the existing attributed value and give it a new attributed value.

The problem is that replacingOccurrences is only possible for string types, as I want to give a new value every time the word appears in the entire sentence.

If I change NSAttributedString to string type, the attributed value is deleted. I must keep the existing values.

How can I do that?


Solution

  • To get this working,

    1. First you need to find the indices of all the duplicate substrings existing in a string. To get that you can use this: https://stackoverflow.com/a/40413665/5716829

    extension String {
        func indicesOf(string: String) -> [Int] {
            var indices = [Int]()
            var searchStartIndex = self.startIndex
    
            while searchStartIndex < self.endIndex,
                let range = self.range(of: string, range: searchStartIndex..<self.endIndex),
                !range.isEmpty
            {
                let index = distance(from: self.startIndex, to: range.lowerBound)
                indices.append(index)
                searchStartIndex = range.upperBound
            }
    
            return indices
        }
    }
    

    2. Next you need to apply your desired attribute to substring at each index, i.e.

        let str = "The problem is that replacingOccurrences Hello is only possible for string types, as I want to give Hello a new value every time Hello the word appears in the entire sentence Hello."
        let indices = str.indicesOf(string: "Hello")
        let attrStr = NSMutableAttributedString(string: str, attributes: [.foregroundColor : UIColor.blue])
        for index in indices
        {
            //You can write your own logic to specify the color for each duplicate. I have used some hardcode indices
            var color: UIColor
            switch index
            {
            case 41:
                color = .orange
            case 100:
                color = .magenta
            case 129:
                color = .green
            default:
                color = .red
            }
            attrStr.addAttribute(.foregroundColor, value: color, range: NSRange(location: index, length: "Hello".count))
        }
    

    Screenshot:

    enter image description here

    Let me know if you still face any issues. Happy Coding..🙂