104

Yes, many people are saying about Rich Text in iPhone/iPad and many knows about NSAttributedString.

But how to use NSAttributedString? I searched for much time, no extract clues for this.

I know how to set up a NSAttributedString, then what should I do to display a text on iPhone/iPad with rich text?

The official docs says it should be used with CoreText.Framework, what does that mean?

Is there any simple way like this?

NSAttributedString *str;
.....
UILabel *label;
label.attributedString = str;
Qantas 94 Heavy
  • 14,790
  • 31
  • 61
  • 78
Jack
  • 3,833
  • 8
  • 37
  • 65
  • The above answer is correct though. Code like that and ensure you add the CoreText framework to your linked frameworks. – mxcl Oct 26 '10 at 12:07
  • Thanks, i left the correct answer to Wes – Jack Oct 27 '10 at 09:53
  • Three20 ooks like a pretty impressive library: https://github.com/facebook/three20 – David H Jul 12 '11 at 16:06
  • 87
    Three20 is crap. – bandejapaisa Feb 12 '12 at 00:10
  • @bandejapaisa, yeah, the worst thing about Three20 is that they don't have good doc – Jack Apr 02 '12 at 17:05
  • 4
    Thats annoying, but I don't think that's the worse thing. For the past 6 months, I've been maintaining a project that uses Three20... some of the things they do with memory baffle me. The code is really fragile as it doesn't handle memory in an orthodox way. It's far better to do what they provide yourself. It's unlikely you're going to need everything they provide. Do it yourself... you'll learn more, it's more fun, you'll probably do it better! – bandejapaisa Apr 02 '12 at 21:50
  • why don't you use: label.attributedText = str; – x4h1d Jul 19 '13 at 10:15

9 Answers9

155

Starting from the iOS 6.0 you can do it like that:

NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"Hello. That is a test attributed string."];
[str addAttribute:NSBackgroundColorAttributeName value:[UIColor yellowColor] range:NSMakeRange(3,5)];
[str addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(10,7)];
[str addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"HelveticaNeue-Bold" size:20.0] range:NSMakeRange(20, 10)];
label.attributedText = str;
RomanN
  • 2,096
  • 2
  • 15
  • 14
  • 60
    The first rule of iOS dev program is not to talk about the iOS dev program. – Jeremy Moyers Aug 21 '12 at 18:40
  • 5
    The second rule of iOS dev program is... see the first rule. – futureelite7 Sep 10 '12 at 03:49
  • 32
    To state that someone has violated the NDA is to confirm that the material presented is indeed in iOS6, and is therefore itself a violation of the NDA. You should write something like "It's not possible to comment on what's in [upcoming version] without breaking NDA". – hatfinch Oct 04 '12 at 09:24
  • Also if you find yourself writing a lot of attributed strings check out this post/category. Makes creation a bit easier. http://www.raizlabs.com/dev/2014/03/nsattributedstring-creation-helpers/ – Alex Rouse Mar 12 '14 at 21:54
81

You should take a look at AliSoftware's OHAttributedLabel. It is a subclass of UILabel that draws an NSAttributedString and also provides convenience methods for setting the attributes of an NSAttributedString from UIKit classes.

From the sample provided in the repo:

#import "NSAttributedString+Attributes.h"
#import "OHAttributedLabel.h"

/**(1)** Build the NSAttributedString *******/
NSMutableAttributedString* attrStr = [NSMutableAttributedString attributedStringWithString:@"Hello World!"];
// for those calls we don't specify a range so it affects the whole string
[attrStr setFont:[UIFont systemFontOfSize:12]];
[attrStr setTextColor:[UIColor grayColor]];
// now we only change the color of "Hello"
[attrStr setTextColor:[UIColor redColor] range:NSMakeRange(0,5)];


/**(2)** Affect the NSAttributedString to the OHAttributedLabel *******/
myAttributedLabel.attributedText = attrStr;
// Use the "Justified" alignment
myAttributedLabel.textAlignment = UITextAlignmentJustify;
// "Hello World!" will be displayed in the label, justified, "Hello" in red and " World!" in gray.

Note: In iOS 6+ you can render attributed strings using the attributedText property of UILabel.

Wes
  • 1,906
  • 1
  • 21
  • 20
  • There is no such thing as a UIAttributedLabel. I think what you're referring to is OHAttributedLabel. – Erik B Dec 28 '10 at 11:16
  • 5
    It was renamed OHAttributedLabel in a [commit in November 2010](https://github.com/AliSoftware/Ali-Cocoa-Classes/commit/b146abd05f314f5de1a829a4163ac0842387d1a9). I've updated my answer. – Wes Jan 09 '11 at 11:00
  • 1
    Thank you Wes! You and Olivier Halligon who wrote the code! Thank you! – DenNukem Feb 04 '11 at 18:52
  • 1
    Thanks @Wes for mentioning my class, and thanks @DenNukem for the credits... I wasn't aware it was so famous ;) Anyway, I did a lot of updates and fixes on this class since the original post, so don't forget to pull the github repo! – AliSoftware Jun 17 '11 at 21:29
  • I get an error on every single line of your code. According to the documentation non of the methods you provided exist in the actual class, I am confused : http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSAttributedString_Class/Reference/Reference.html – aryaxt Jun 29 '11 at 17:10
  • Ok I figured out what the problem was. The NSAttributedString for iphone doesn't have all functions that Mac OSX version has. I guess the one for the iphone is a light version. – aryaxt Jul 03 '11 at 20:19
  • You should also make sure you include "NSAttributedString+Attributes.m" – Wes Jul 08 '11 at 01:10
  • @barfoon: add a UILabel in Xcode and set its class to OHAttributedLabel – JRG Apr 15 '12 at 12:54
  • @JRG - not everyone creates objects in IB all the time – barfoon Apr 17 '12 at 20:27
  • Indeed, as your comment indicates. My mistake. – JRG Apr 18 '12 at 02:06
  • Great job with the class and category. It should be part of the framework! – Kasper Munck Jul 19 '12 at 19:18
  • This does not really answer the users question. Instead of explaining how to use attributed strings, the explain how to use an alternative. – Billy Lazzaro Oct 23 '13 at 17:22
15

You should try TTTAttributedLabel. It's a drop-in replacement for UILabel that works with NSAttributedString and is performant enough for UITableViewCells.

mattt
  • 19,450
  • 7
  • 69
  • 83
6

Answer for UILabel attributed text alignment on iOS 6: Use NSMutableAttributedString and add NSMutableParagraphStyle to the attribute. Something like this:

NSString *str = @"Hello World!";
NSRange strRange = NSMakeRange(0, str.length);
NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc] initWithString:str];

NSMutableParagraphStyle *paragrahStyle = [[NSMutableParagraphStyle alloc] init];
[paragrahStyle setAlignment:NSTextAlignmentCenter];
[attributedStr addAttribute:NSParagraphStyleAttributeName value:paragrahStyle range:strRange];

myUILabel.attributedText = attributedStr;
elou
  • 61
  • 1
  • 1
6

I thought it would be useful to give an example of parsing a (simplified) HTML string, to create an NSAttributedString.

It isn't complete - it only handles <b> and <i> tags, for starters, and doesn't bother with any error handling - but is hopefully also a useful example of how to get started with NSXMLParserDelegate ...


@interface ExampleHTMLStringToAttributedString : NSObject<NSXMLParserDelegate>

+(NSAttributedString*) getAttributedStringForHTMLText:(NSString*)htmlText WithFontSize:(CGFloat)fontSize;

@end

@interface ExampleHTMLStringToAttributedString()
@property NSString *mpString;
@property NSMutableAttributedString *mpAttributedString;

@property CGFloat mfFontSize;
@property NSMutableString *appendThisString;
@property BOOL mbIsBold;
@property BOOL mbIsItalic;
@end

@implementation ExampleHTMLStringToAttributedString
@synthesize mpString;
@synthesize mfFontSize;
@synthesize mpAttributedString;
@synthesize appendThisString;
@synthesize mbIsBold;
@synthesize mbIsItalic;

+(NSAttributedString*) getAttributedStringForHTMLText:(NSString*)htmlText WithFontSize:(CGFloat)fontSize {

    ExampleHTMLStringToAttributedString *me = [[ExampleHTMLStringToAttributedString alloc] initWithString:htmlText];
    return [me getAttributedStringWithFontSize:fontSize];
}

- (id)initWithString:(NSString*)inString {
    self = [super init];
    if (self) {
        if ([inString hasPrefix:@""]) {
          mpString = inString;
        } else {
            mpString = [NSString stringWithFormat:@"%@", inString];
        }
        mpAttributedString = [NSMutableAttributedString new];
    }
    return self;
}

-(NSAttributedString*) getAttributedStringWithFontSize:(CGFloat)fontSize {

    mfFontSize = fontSize;

    // Parse the XML
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:[mpString dataUsingEncoding:NSUTF8StringEncoding]];
    parser.delegate = self;
    if (![parser parse]) {
        return nil;
    }

    return mpAttributedString;
}

-(void) appendTheAccumulatedText {
    UIFont *theFont = nil;

    if (mbIsBold && mbIsItalic) {
        // http://stackoverflow.com/questions/1384181/italic-bold-and-underlined-font-on-iphone
        theFont = [UIFont fontWithName:@"Helvetica-BoldOblique" size:mfFontSize];
    } else if (mbIsBold) {
       theFont = [UIFont boldSystemFontOfSize:mfFontSize];
    } else if (mbIsItalic) {
        theFont = [UIFont italicSystemFontOfSize:mfFontSize];
    } else {
        theFont = [UIFont systemFontOfSize:mfFontSize];
    }

    NSAttributedString *appendThisAttributedString =
    [[NSAttributedString alloc]
     initWithString:appendThisString
     attributes:@{NSFontAttributeName : theFont}];

    [mpAttributedString appendAttributedString:appendThisAttributedString];

    [appendThisString setString:@""];
}

#pragma NSXMLParserDelegate delegate

-(void)parserDidStartDocument:(NSXMLParser *)parser{
    appendThisString = [NSMutableString new];
    mbIsBold = NO;
    mbIsItalic = NO;
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    if ([elementName isEqualToString:@"body"]){
    } else if ([elementName isEqualToString:@"i"]) {
      [self appendTheAccumulatedText];
        mbIsItalic = YES;
    } else if ([elementName isEqualToString:@"b"]) {
      [self appendTheAccumulatedText];
        mbIsBold = YES;
    }
}

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    if ([elementName isEqualToString:@"body"]){
      [self appendTheAccumulatedText];
    } else if ([elementName isEqualToString:@"i"]) {
      [self appendTheAccumulatedText];
      mbIsItalic = NO;
    } else if ([elementName isEqualToString:@"b"]) {
        [self appendTheAccumulatedText];
        mbIsBold = NO;
    }
}

-(void)parserDidEndDocument:(NSXMLParser *)parser{
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    [appendThisString appendString:string];
}

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
}

@end


To use, do something like this:


  self.myTextView.attributedText = [ExampleHTMLStringToAttributedString getAttributedStringForHTMLText:@"this is <b>bold</b> text" WithFontSize:self.myTextView.pointSize];

Pete
  • 724
  • 8
  • 9
6

Is there any simple ways like

NSAttributedString *str;

UILabel *label;

label.attributedString = str;

Almost. Just use a CATextLayer. It has a string property that you can set to an NSAttributedString.

EDIT (November, 2012): Of course all this has changed in iOS 6. In iOS 6, you can do exactly what the OP asked for - assign an attributed string directly to a label's attributedText.

matt
  • 447,615
  • 74
  • 748
  • 977
  • 1
    Could you be more specific, e.g. provide an example usage? – William Niu Apr 24 '12 at 05:22
  • 1
    Yes, it's called my book, Programming iOS 5. Here's the code example from the book: https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/ch23p689styledText1/p579p593styleText1/StyledText.m – matt Apr 24 '12 at 18:22
5

Starting from the iOS 6.0 you can do it like that: another sample code.

NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"This is my test code to test this label style is working or not on the text to show other user"];

[str addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0,31)];
[str addAttribute:NSBackgroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(61,10)];

[str addAttribute:NSFontAttributeName value: [UIFont fontWithName:@"Helvetica-Bold" size:13.0] range:NSMakeRange(32, 28)];
[str addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Helvetica-Bold" size:13.0] range:NSMakeRange(65, 20)];

_textLabel.attributedText = str;
Ayaz
  • 1,398
  • 15
  • 29
2

For Swift use this,

It will make Titl texts bold,

var title = NSMutableAttributedString(string: "Title Text")

    title.addAttributes([NSFontAttributeName: UIFont(name: "AvenirNext-Bold", size: iCurrentFontSize)!], range: NSMakeRange(0, 4))

    label.attributedText = title
Mohammad Zaid Pathan
  • 14,352
  • 6
  • 84
  • 112
2

I know it is little bit late, But it will be useful to other,

NSMutableAttributedString* attrStr = [[NSMutableAttributedString alloc] initWithString:@"string" attributes:@{NSForegroundColorAttributeName:[UIColor blackColor]}];

[self.label setAttributedText:newString];

Add the desired attribute to the dictionary and pass it as a attributes parameter

satheesh
  • 2,541
  • 2
  • 10
  • 18