0

I am trying to add color to 2 words in a string. This is the code I am using:

        var HighScore:Int = 0
        var CurrentScore:Int = 0

        let stringOne = "You have managed to score \(CurrentScore). Current record is \(self.HighScore). Play again and give it another try!"
        let stringTwo = "\(CurrentScore)"
        let stringThree = "\(HighScore)"

        let range1 = (stringOne as NSString).range(of: stringTwo)
        let range2 = (stringOne as NSString).range(of: stringThree)

        let attributedText = NSMutableAttributedString.init(string: stringOne)

        attributedText.addAttribute(NSForegroundColorAttributeName, value: UIColor.init(netHex: 0x00b4ff) , range: range1)
        attributedText.addAttribute(NSForegroundColorAttributeName, value: UIColor.init(netHex: 0x00b4ff) , range: range2)

        gameOverDescriptionLabel.attributedText = attributedText

The problem I have is that if CurrentScore and HighScore is the same(ex: 2 & 2) the color on the range2 still stays white, but if they are not equal(2 & 1 or 1 & 2) both gets the color I have choosen.

Any suggestions?

Sibling Thor
  • 57
  • 1
  • 6

4 Answers4

1

If the current score and high score are the same string, searching for the latter finds the former (because the search starts at the beginning).

There are lots of other, better ways to do this.

  • Perform the second search in a range starting after the result of the first search (range(of:) has a range: parameter, but you are not using it)

  • Instead of looking for the range of the high score, search for the surrounding boilerplate ("You have managed to score" and so on) and figure out where the numbers must be.

  • Use NSScanner or regular expressions to find the numerical expressions embedded in the string.

  • My favorite: mark each of the numbers with an "invisible" attribute and search for that attribute so that you can find the numbers reliably (example here).

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I don't understand how I could implement the "invisible" attribute in my code. Still haven't fixed my issue.. – Sibling Thor Jan 21 '17 at 20:33
  • Well, I gave you a choice of four perfectly good ideas, and with the last one I gave you actual code that demonstrates the technique. My work here is done. The problem now seems to be that you don't know an answer when you hear it. – matt Jan 21 '17 at 21:12
  • No need to be cocky, mam. I haven't been working much with `NSMutableAttributedString ` so i'm not quite sure what exactly to do. Please be more friendly with your comments. – Sibling Thor Jan 21 '17 at 21:17
1

Add this to the top or bottom of your .swift file:

extension NSMutableAttributedString {
    func bold(_ text:String) -> NSMutableAttributedString {
        let attrs:[String:AnyObject] = [NSForegroundColorAttributeName: UIColor.init(netHex: 0x00b4ff)]
        let boldString = NSMutableAttributedString(string:"\(text)", attributes:attrs)
        self.append(boldString)
        return self
    }

    func normal(_ text:String)->NSMutableAttributedString {
        let normal =  NSAttributedString(string: text)
        self.append(normal)
        return self
    }
}

To code below is the usage, you can edit it how you'd like, but I have made it so you can easy just copy&paste it to your project:

            let formattedString = NSMutableAttributedString()
            formattedString
                .normal("You have managed to score ")
                .bold("\(CurrentScore)")
                .normal(". Current record is ")
                .bold("\(HighScore)")
                .normal(". Play again and give it another try!")

            gameOverDescriptionLabel.attributedText = formattedString
Erik Auranaune
  • 1,384
  • 1
  • 12
  • 27
0

A solution without searching for the range would be to create 2 separate NSMutableAttributedString for current score and high score, and then append everything together.

let currentScoreString = NSMutableAttributedString(...)
let highscoreString = NSMutableAttributedString(...)

let finalString = NSMutableAttributedString(string: "You have managed to score ").append(currentScoreString)....
TheAmateurProgrammer
  • 9,252
  • 8
  • 52
  • 71
  • I tried doing `currentScoreString.append((CurrentScore as Int) as! NSAttributedString)` but that made it crash. Also crash if I use `CurrentScore as AnyObject`.. – Sibling Thor Jan 19 '17 at 20:17
  • You can't just convert an int into an NSAttributedString! You have to initialize a new NSAttributedString object. I've made some changes in the first 2 lines to show that. – TheAmateurProgrammer Jan 19 '17 at 20:23
  • This is another attempt i did: http://pastebin.com/dB9bk0sy - Gives no error, but the color does still not change if they are equal... – Sibling Thor Jan 20 '17 at 21:37
0
//MARK: forgroundColor

open var foregroundColor: UIColor? {
    didSet {
        textAttributes[NSForegroundColorAttributeName] = foregroundColor
        self.attributedText = NSAttributedString(string: self.text, attributes: textAttributes)
    }
}

//MARK: backgroundColor
open var textBackgroundColor: UIColor? {
    didSet {
        textAttributes[NSBackgroundColorAttributeName] = textBackgroundColor
        self.attributedText = NSAttributedString(string: self.text, attributes: textAttributes)
    }
}
Rohan Dave
  • 251
  • 1
  • 7