Oleg Tretiakov
Oleg Tretiakov

Reputation: 159

In Swift NSAttributedString has more characters than String?

I am trying to add attributes to some ranges in Swift String. I found ranges of first and last symbol in substring and color the text between them (including) in red.

let mutableString = NSMutableAttributedString(string: text)
let str = mutableString.string
//Red symbols
var t = 0
let symbols = mutableString.string.characters.count
while t < symbols {
    if str[t] == "[" {
    let startIndex = t
    while str[t] != "]" {
        t += 1
    }
    t += 1
    let endIndex = t

    mutableString.addAttribute(
        NSForegroundColorAttributeName,                    
        value: UIColor.redColor(),   
        range: NSMakeRange(startIndex, endIndex - startIndex))
    }
    t += 1
}

But I found that ranges in String and in NSMutableAttributedString are not equal. Range in String is shorter (this text is not in Unicode encoding). Is there a some way to find ranges not in underlying String but in NSAttributedString to find it correctly?

Example:

print(mutableString.length) //550
print(mutableString.string.characters.count) //548

Why is this difference?

Upvotes: 2

Views: 6170

Answers (3)

Oleg Tretiakov
Oleg Tretiakov

Reputation: 159

Yes, I found it. Windows end-of-line "\r\n" is two symbols in NSAttributedString but only one character in Swift String. I use checking in my code:

let symbols = mutableString.string.characters.count
var extendedSymbols = 0
    while t < symbols {
        if str[t] == "\r\n" { extendedSymbols += 1 }
        else if str[t] == "[" {
            let startIndex = t + extendedSymbols
            while str[t] != "]" {
                t += 1
            }
            t += 1
            let endIndex = t + extendedSymbols

            mutableString.addAttribute(
                NSForegroundColorAttributeName,
                value: UIColor.redColor(), 
                range: NSMakeRange(startIndex, endIndex - startIndex))
        }
        t += 1
    }

Thank you all for help!!!

Upvotes: 3

matt
matt

Reputation: 534885

Distinguish between String and NSString, even though they are bridged to one another. String is native Swift, and you define a range in terms of String character index. NSString is Cocoa (Foundation), and you define a range in terms of NSRange.

Upvotes: 3

Oleg Gordiichuk
Oleg Gordiichuk

Reputation: 15512

Yes it is possible to find ranges in NSMutableAttributedString.

Example :

let text = "[I love Ukraine!]"

var start = text.rangeOfString("[")
var finish = text.rangeOfString("]")

let mutableString = NSMutableAttributedString(string: text)

let startIndex = mutableString.string.rangeOfString("[")
let finishIndex = mutableString.string.rangeOfString("]")

Example output from playground: enter image description here

Upvotes: 4

Related Questions