170

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.

4
  • this Commented Jan 11, 2013 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? Commented Jan 11, 2013 at 22:09
  • 2
    possible duplicate of How do you use NSAttributedString? Commented Jan 11, 2013 at 22:54
  • Use this library, it's petty simple. github.com/iOSTechHub/AttributedString Commented Sep 2, 2018 at 17:57

9 Answers 9

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

6 Comments

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.
@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.
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).
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.
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. </rant>
|
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]];

7 Comments

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.
I copied my answer from here stackoverflow.com/questions/14231879/…
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'
Just tryin to figure otu what "texts"
@Morkrom: if you see 2nd comment in this answer, then you will get to know :p
|
60

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.

Comments

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

Comments

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))

Comments

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)
}

Comments

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

Comments

1

One liner for Swift:

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

Comments

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

..

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.