Swift 3: How to apply attributes to parts of string

So the method I used in Swift 2 no longer works because of changes in Swift 3, regarding String indices and ranges. Previously I had

func configureLabel(defaultColor: UIColor, highlightColor: UIColor, boldKeyText: Bool) {
    if let index = self.text?.characters.indexOf(Character("|")) {
        self.text = self.text!.stringByReplacingOccurrencesOfString("|", withString: "")
        let labelLength:Int = Int(String(index))! // Now returns nil

        var keyAttr: [String:AnyObject] = [NSForegroundColorAttributeName: highlightColor]
        var valAttr: [String:AnyObject] = [NSForegroundColorAttributeName: defaultColor]
        if boldKeyText {
            keyAttr[NSFontAttributeName] = UIFont.systemFontOfSize(self.font.pointSize)
            valAttr[NSFontAttributeName] = UIFont.systemFontOfSize(self.font.pointSize, weight: UIFontWeightHeavy)
        }

        let attributeString = NSMutableAttributedString(string: self.text!)
        attributeString.addAttributes(keyAttr, range: NSRange(location: 0, length: (self.text?.characters.count)!))
        attributeString.addAttributes(valAttr, range: NSRange(location: 0, length: labelLength))

        self.attributedText = attributeString

    }
}

Basically I would be able to take a string like "First Name:| Gary Oak" and have all the parts before and after the | character be different colors, or make part of it bold, but the line I commented above no longer returns a value, which breaks everything else afterwards. Any ideas on how to do this?

Upvotes: 0

Views: 1880

Answers (1)

Anton Rogachevskyi
Anton Rogachevskyi

Reputation: 219

In Swift 3 you can use something like this:

func configureLabel(defaultColor: UIColor, highlightColor: UIColor, boldKeyText: Bool) {      

    if let index = self.text?.characters.index(of: Character("|")) {
        self.text = self.text!.replacingOccurrences(of: "|", with: "")
        let position = text.distance(from: text.startIndex, to: index)

        let labelLength:Int = Int(String(describing: position))!

        var keyAttr: [String:AnyObject] = [NSForegroundColorAttributeName: defaultColor]
        var valAttr: [String:AnyObject] = [NSForegroundColorAttributeName: highlightColor]
        if boldKeyText {
            keyAttr[NSFontAttributeName] = UIFont.systemFont(ofSize: self.font.pointSize)
            valAttr[NSFontAttributeName] = UIFont.systemFont(ofSize: self.font.pointSize, weight: UIFontWeightHeavy)
        }

        let attributeString = NSMutableAttributedString(string: self.text!)
        attributeString.addAttributes(keyAttr, range: NSRange(location: 0, length: (self.text?.characters.count)!))
        attributeString.addAttributes(valAttr, range: NSRange(location: 0, length: labelLength))

        self.attributedText = attributeString

    }

}

the main idea that using let position = text.distance(from: text.startIndex, to: index) you got not the integer representation of string position but the string Index value. Using text.distance(from: text.startIndex, to: index) you can find int position for string Index

Upvotes: 2

Related Questions