168

I have a slider for a survey that display the following strings based on the value of the slider: "Very Bad, Bad, Okay, Good, Very Good".

Here is the code for the slider:

- (IBAction) sliderValueChanged:(UISlider *)sender {
    scanLabel.text = [NSString stringWithFormat:@" %.f", [sender value]];
    NSArray *texts=[NSArray arrayWithObjects:@"Very Bad", @"Bad", @"Okay", @"Good", @"Very Good", @"Very Good", nil];
    NSInteger sliderValue=[sender value]; //make the slider value in given range integer one.
    self.scanLabel.text=[texts objectAtIndex:sliderValue];
}

I want "Very Bad" to be red, "Bad" to be orange, "Okay" to be yellow, "Good" and "Very Good" to be green.

I don't understand how to use NSAttributedString to get this done.

James Webster
  • 31,873
  • 11
  • 70
  • 114
Adam
  • 1,817
  • 2
  • 11
  • 7
  • [this](https://github.com/mattt/TTTAttributedLabel) –  Jan 11 '13 at 22:06
  • You mean a UISlider? That doesn't have a label. So basically its a about a UILabel with a font color? Or do you want a part of the text colored? – Roger Jan 11 '13 at 22:09
  • 2
    possible duplicate of [How do you use NSAttributedString?](http://stackoverflow.com/questions/3482346/how-do-you-use-nsattributedstring) – John Parker Jan 11 '13 at 22:54
  • Use this library, it's petty simple. https://github.com/iOSTechHub/AttributedString – Ashish Chauhan Sep 02 '18 at 17:57

9 Answers9

214

There is no need for using NSAttributedString. All you need is a simple label with the proper textColor. Plus this simple solution will work with all versions of iOS, not just iOS 6.

But if you needlessly wish to use NSAttributedString, you can do something like this:

UIColor *color = [UIColor redColor]; // select needed color
NSString *string = ... // the string to colorize
NSDictionary *attrs = @{ NSForegroundColorAttributeName : color };
NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:string attributes:attrs];
self.scanLabel.attributedText = attrStr;
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • 4
    I don't understand all of the down votes. My answer is much simpler than using an attributed string. The OP has no need to use `NSAttributedString` for this task. It would be one thing if the label's text needed multiple attributes but it doesn't. The whole label needs to be one color at a time. – rmaddy Jan 19 '15 at 18:20
  • @RubénE.Marín But that's the problem. The OP mistakenly thought that the solution required using `NSAttributedString`. So that is what they asked for. The real question should have been *"How to set the label's color based on its value"*. I pointed out that the solution does not require `NSAttributedString` and showed a much simpler answer. And the OP agreed by accepting my much simpler answer. If the OP **really** wanted `NSAttributedString`, they wouldn't have accepted my answer. So there is no reason for the down votes. I answered the true question and the OP accepted. – rmaddy Mar 11 '15 at 14:41
  • 29
    In that case, I would have solved the question with NSAttributedString and, after that, I would have pointed out your simpler and more efficient solution for the particular case of the OP. People coming to this question may feel frustrated by your solution because they are looking for ways to change text color on NSAttributedString (and that would explain your down votes). – Ruben Marin Mar 12 '15 at 15:20
  • 17
    Rubén is right: I came here because I do need to set the color in an attributed string, because I'm building a compound attributed string with multiple colors and font sizes. And the key piece of information I needed was the `NSForegroundColorAttributeName` key, which I had a hard time finding in the Apple docs. – Erik van der Neut May 13 '15 at 10:53
  • 7
    Thank you for still answering the question!! even if OP didn't actually need it. So many times I google something, end up on a stack overflow question that's exactly what I'm looking for, only to find that the wise-ass answering the question decided the OP didn't actually need what the question title was asking for and answered a completely different question. Well, people in the future coming from search results, of which there might be 1000's as opposed to the 1 OP, might actually want a solution to the question asked in the title of the post. – danny Jun 08 '15 at 16:51
  • I came here from a Google search and was anticipating having to down vote this answer based on the excerpt I saw before clicking on the link to bring me here. Glad you realized that it isn't strictly about what the OP needs, but what others with a similar question are looking for as well. I'm glad you edited your answer to provide the correct solution. +1 – Stunner Jan 09 '18 at 05:57
116

Use something like this (Not compiler checked)

NSMutableAttributedString *string = [[NSMutableAttributedString alloc]initWithString:self.text.text];
NSRange range=[self.myLabel.text rangeOfString:texts[sliderValue]]; //myLabel is the outlet from where you will get the text, it can be same or different

NSArray *colors=@[[UIColor redColor],
                  [UIColor redColor],
                  [UIColor yellowColor],
                  [UIColor greenColor]
                 ];

[string addAttribute:NSForegroundColorAttributeName 
               value:colors[sliderValue] 
               range:range];           

[self.scanLabel setAttributedText:texts[sliderValue]];
Anoop Vaidya
  • 46,283
  • 15
  • 111
  • 140
  • Hey Anoop, glad to see you again! I treid the code you provided, I replaced self.text.text with self.scanLabel.text, but I'm getting an error at "word". I tried replacing it with @"Very Bad" with no luck. – Adam Jan 11 '13 at 22:18
  • I copied my answer from here http://stackoverflow.com/questions/14231879/is-it-possible-to-change-color-of-single-word-in-uitextview-and-uitextfield/14231900#14231900 – Anoop Vaidya Jan 11 '13 at 22:20
  • Thanks Anoop, but no luck for me. -[__NSCFString _ui_synthesizeAttributedSubstringFromRange:usingDefaultAttributes:]: unrecognized selector sent to instance 0x1f845af0 2013-01-11 16:27:34.939 yellaProto[7829:907] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString _ui_synthesizeAttributedSubstringFromRange:usingDefaultAttributes:]: unrecognized selector sent to instance 0x1f845af0' – Adam Jan 11 '13 at 22:28
  • Just tryin to figure otu what "texts" – Morkrom Jun 24 '13 at 18:15
  • @Morkrom: if you see 2nd comment in this answer, then you will get to know :p – Anoop Vaidya Aug 02 '13 at 06:16
  • Downvoted. If you're using the answer from somewhere else, mention it in the answer, not in the comments. – Dragos Strugar Dec 26 '19 at 10:30
  • @DragosStrugar: I copied my answer! – Anoop Vaidya Dec 26 '19 at 17:33
58

In Swift 4/5:

// Custom color
let greenColor = UIColor(red: 10/255, green: 190/255, blue: 50/255, alpha: 1)
// create the attributed colour
let attributedStringColor = [NSAttributedStringKey.foregroundColor : greenColor];
// create the attributed string
let attributedString = NSAttributedString(string: "Hello World!", attributes: attributedStringColor)
// Set the label
label.attributedText = attributedString

In Swift 3:

// Custom color
let greenColor = UIColor(red: 10/255, green: 190/255, blue: 50/255, alpha: 1)
// create the attributed color
let attributedStringColor : NSDictionary = [NSForegroundColorAttributeName : greenColor];
// create the attributed string
let attributedString = NSAttributedString(string: "Hello World!", attributes: attributedStringColor as? [String : AnyObject])
// Set the label
label.attributedText = attributedString 

Enjoy.

App Dev Guy
  • 5,396
  • 4
  • 31
  • 54
35

For Swift 5:

var attributes = [NSAttributedString.Key: AnyObject]()
attributes[.foregroundColor] = UIColor.red

let attributedString = NSAttributedString(string: "Very Bad", attributes: attributes)

label.attributedText = attributedString

For Swift 4:

var attributes = [NSAttributedStringKey: AnyObject]()
attributes[.foregroundColor] = UIColor.red

let attributedString = NSAttributedString(string: "Very Bad", attributes: attributes)

label.attributedText = attributedString

For Swift 3:

var attributes = [String: AnyObject]()
attributes[NSForegroundColorAttributeName] = UIColor.red

let attributedString = NSAttributedString(string: "Very Bad", attributes: attributes)

label.attributedText = attributedString
pableiros
  • 14,932
  • 12
  • 99
  • 105
8

You can create NSAttributedString

NSDictionary *attributes = @{ NSForegroundColorAttributeName : [UIColor redColor] };
NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:@"My Color String" attributes:attrs];

OR NSMutableAttributedString to apply custom attributes with Ranges.

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@%@", methodPrefix, method] attributes: @{ NSFontAttributeName : FONT_MYRIADPRO(48) }];
[attributedString addAttribute:NSFontAttributeName value:FONT_MYRIADPRO_SEMIBOLD(48) range:NSMakeRange(methodPrefix.length, method.length)];

Available Attributes: NSAttributedStringKey


UPDATE:

Swift 5.1

let message: String = greeting + someMessage
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 2.0
    
// Note: UIFont(appFontFamily:ofSize:) is extended init.
let regularAttributes: [NSAttributedString.Key : Any] = [.font : UIFont(appFontFamily: .regular, ofSize: 15)!, .paragraphStyle : paragraphStyle]
let boldAttributes = [NSAttributedString.Key.font : UIFont(appFontFamily: .semiBold, ofSize: 15)!]

let mutableString = NSMutableAttributedString(string: message, attributes: regularAttributes)
mutableString.addAttributes(boldAttributes, range: NSMakeRange(0, greeting.count))
Community
  • 1
  • 1
Lal Krishna
  • 15,485
  • 6
  • 64
  • 84
5

With Swift 4, NSAttributedStringKey has a static property called foregroundColor. foregroundColor has the following declaration:

static let foregroundColor: NSAttributedStringKey

The value of this attribute is a UIColor object. Use this attribute to specify the color of the text during rendering. If you do not specify this attribute, the text is rendered in black.

The following Playground code shows how to set the text color of an NSAttributedString instance with foregroundColor:

import UIKit

let string = "Some text"
let attributes = [NSAttributedStringKey.foregroundColor : UIColor.red]
let attributedString = NSAttributedString(string: string, attributes: attributes)

The code below shows a possible UIViewController implementation that relies on NSAttributedString in order to update the text and text color of a UILabel from a UISlider:

import UIKit

enum Status: Int {
    case veryBad = 0, bad, okay, good, veryGood

    var display: (text: String, color: UIColor) {
        switch self {
        case .veryBad:  return ("Very bad", .red)
        case .bad:      return ("Bad", .orange)
        case .okay:     return ("Okay", .yellow)
        case .good:     return ("Good", .green)
        case .veryGood: return ("Very good", .blue)
        }
    }

    static let minimumValue = Status.veryBad.rawValue
    static let maximumValue = Status.veryGood.rawValue
}
final class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var slider: UISlider!
    var currentStatus: Status = Status.veryBad {
        didSet {
            // currentStatus is our model. Observe its changes to update our display
            updateDisplay()
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Prepare slider
        slider.minimumValue = Float(Status.minimumValue)
        slider.maximumValue = Float(Status.maximumValue)

        // Set display
        updateDisplay()
    }

    func updateDisplay() {
        let attributes = [NSAttributedStringKey.foregroundColor : currentStatus.display.color]
        let attributedString = NSAttributedString(string: currentStatus.display.text, attributes: attributes)
        label.attributedText = attributedString
        slider.value = Float(currentStatus.rawValue)
    }

    @IBAction func updateCurrentStatus(_ sender: UISlider) {
        let value = Int(sender.value.rounded())
        guard let status = Status(rawValue: value) else { fatalError("Could not get Status object from value") }
        currentStatus = status
    }

}

Note however that you don't really need to use NSAttributedString for such an example and can simply rely on UILabel's text and textColor properties. Therefore, you can replace your updateDisplay() implementation with the following code:

func updateDisplay() {
    label.text = currentStatus.display.text
    label.textColor = currentStatus.display.color
    slider.value = Float(currentStatus.rawValue)
}
Imanou Petit
  • 89,880
  • 29
  • 256
  • 218
5

Update for Swift 5.2

var attributes = [NSAttributedString.Key: AnyObject]()

attributes[.foregroundColor] = UIColor.blue

let attributedString = NSAttributedString(string: "Very Bad",
attributes: attributes)

label.attributedText = attributedString
Mithra Singam
  • 1,905
  • 20
  • 26
1

One liner for Swift:

NSAttributedString(string: "Red Text", attributes: [.foregroundColor: UIColor.red])
0

I love making things easier , try this one

-(NSArray *) reArrangeArrays:(NSArray *)iObjects {
    
    NSMutableArray *Words = [[NSMutableArray alloc] init];
    NSMutableArray *Colors = [[NSMutableArray alloc] init];
    
    CFIndex OneThree = 0;
    CFIndex TwoFour = 1;
    for (CFIndex iCounter = 0; iCounter < iObjects.count; iCounter ++) {
        
        [Words addObject:[iObjects objectAtIndex:OneThree]];
        [Colors addObject:[iObjects objectAtIndex:TwoFour]];
        
        OneThree = OneThree + 2;
        TwoFour = TwoFour + 2;
        
        if (OneThree > iObjects.count || TwoFour > iObjects.count)
            break;
    }
    
    return @[[NSArray arrayWithArray:Words],[NSArray arrayWithArray:Colors]];
}

+(NSMutableAttributedString *) OriginalText:(NSString *)OriginalText WordsAndColors:(NSArray *)WordsAndColors TheRestOfTheTextColor:(UIColor *)TheRestColor {
    
    NSArray *Text = [[self.alloc reArrangeArrays:WordsAndColors] objectAtIndex:0];
    NSArray *Color = [[self.alloc reArrangeArrays:WordsAndColors] objectAtIndex:1];

    NSMutableAttributedString *MutableAttString = [[NSMutableAttributedString alloc] initWithString:OriginalText attributes:@{NSForegroundColorAttributeName : TheRestColor}];

    NSString *text = OriginalText;

    if (OriginalText != nil) {

    for (NSUInteger Counter = 0; Counter < Color.count; Counter ++) {

    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:[NSString stringWithFormat:@"(%@)",[Text objectAtIndex:Counter]] options:kNilOptions error:nil];

    NSRange range = NSMakeRange(0 ,text.length);

    [regex enumerateMatchesInString:text options:kNilOptions range:range usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {

        NSRange subStringRange = [result rangeAtIndex:0];

        [MutableAttString addAttribute:NSForegroundColorAttributeName value:[Color objectAtIndex:Counter] range:subStringRange];

    }];


    }
}
    return MutableAttString;
}

And this is how to use


 NSString *Text = @"Made by @CrazyMind90";
        
 NSMutableAttributedString *AttriString = [ViewController OriginalText:Text
            WordsAndColors:@[
                
            @"Made",UIColor.redColor,
            @"by",UIColor.yellowColor,
            @"@CrazyMind90",UIColor.blueColor,
            
            ]
            
           TheRestOfTheTextColor:UIColor.whiteColor];
        
    
           //Not TextView.text BUT TextView.attributedText
           TextView.attributedText = AttriString;

The result

..

CrazyMind90
  • 11
  • 1
  • 2