Change string color with NSAttributedString?

IosCocoa TouchNsattributedstring

Ios Problem Overview


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.

Ios Solutions


Solution 1 - Ios

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;

Solution 2 - Ios

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]];

Solution 3 - Ios

In Swift 4:

// 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.

Solution 4 - Ios

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

Solution 5 - Ios

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

Solution 6 - Ios

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

Solution 7 - Ios

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

Solution 8 - Ios

One liner for Swift:

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

Solution 9 - Ios

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

..

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAdamView Question on Stackoverflow
Solution 1 - IosrmaddyView Answer on Stackoverflow
Solution 2 - IosAnoop VaidyaView Answer on Stackoverflow
Solution 3 - IosApp Dev GuyView Answer on Stackoverflow
Solution 4 - IospableirosView Answer on Stackoverflow
Solution 5 - IosLal KrishnaView Answer on Stackoverflow
Solution 6 - IosImanou PetitView Answer on Stackoverflow
Solution 7 - IosMithra SingamView Answer on Stackoverflow
Solution 8 - IosFedotchenco DenisView Answer on Stackoverflow
Solution 9 - IosCrazyMind90View Answer on Stackoverflow