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?

4 Answers 4

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

1 Comment

Works like a charm. Thanks!:)))
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).

3 Comments

I don't understand how I could implement the "invisible" attribute in my code. Still haven't fixed my issue..
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.
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.
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)....

3 Comments

I tried doing currentScoreString.append((CurrentScore as Int) as! NSAttributedString) but that made it crash. Also crash if I use CurrentScore as AnyObject..
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.
This is another attempt i did: pastebin.com/dB9bk0sy - Gives no error, but the color does still not change if they are equal...
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)
    }
}

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.