iphone / ipad: ¿Cómo se usa exactamente NSAttributedString?

102

Sí, mucha gente dice sobre el texto enriquecido en iPhone / iPad y muchos lo saben NSAttributedString.

¿Pero cómo se usa NSAttributedString? Busqué durante mucho tiempo, sin extraer pistas para esto.

Sé cómo configurar un NSAttributedString, entonces, ¿qué debo hacer para mostrar un texto en iPhone / iPad con texto enriquecido?

Los documentos oficiales dicen que debe usarse con CoreText.Framework, ¿qué significa eso?

¿Existe alguna forma sencilla como esta?

NSAttributedString *str;
.....
UILabel *label;
label.attributedString = str;
Jack
fuente
Sin embargo, la respuesta anterior es correcta. Codifique así y asegúrese de agregar el marco CoreText a sus marcos vinculados.
mxcl
Gracias, le dejé la respuesta correcta a Wes
Jack
Three20 ooks como una biblioteca bastante impresionante: github.com/facebook/three20
David H
87
Three20 es una mierda.
bandejapaisa
4
Eso es molesto, pero no creo que sea lo peor. Durante los últimos 6 meses, he estado manteniendo un proyecto que usa Three20 ... algunas de las cosas que hacen con la memoria me desconciertan. El código es realmente frágil ya que no maneja la memoria de forma ortodoxa. Es mucho mejor hacer lo que te ofrecen. Es poco probable que necesite todo lo que ofrecen. Hágalo usted mismo ... aprenderá más, es más divertido, ¡probablemente lo hará mejor!
bandejapaisa

Respuestas:

79

Debería echar un vistazo a OHAttributedLabel de AliSoftware . Es una subclase de UILabel que dibuja un NSAttributedString y también proporciona métodos convenientes para establecer los atributos de un NSAttributedString de las clases UIKit.

De la muestra proporcionada en el repositorio:

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

Nota: En iOS 6+, puede representar cadenas con atributos utilizando la propiedad attributeText de UILabel.

Wes
fuente
No existe tal cosa como UIAttributedLabel. Creo que te refieres a OHAttributedLabel.
Erik B
5
Se le cambió el nombre a OHAttributedLabel en una confirmación en noviembre de 2010 . Actualicé mi respuesta.
Wes
1
¡Gracias Wes! ¡Tú y Olivier Halligon, que escribieron el código! ¡Gracias!
DenNukem
1
Gracias @Wes por mencionar mi clase, y gracias @DenNukem por los créditos ... No sabía que era tan famoso;) De todos modos, hice muchas actualizaciones y correcciones en esta clase desde la publicación original, así que no ' ¡No olvides extraer el repositorio de github!
AliSoftware
Recibo un error en cada línea de su código. De acuerdo con la documentación
ninguno
155

A partir de iOS 6.0 puedes hacerlo así:

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
fuente
60
La primera regla del programa de desarrollo de iOS es no hablar del programa de desarrollo de iOS.
Jeremy Moyers
5
La segunda regla del programa de desarrollo de iOS es ... ver la primera regla.
futureelite7
32
Afirmar que alguien ha violado el NDA es confirmar que el material presentado está realmente en iOS6 y, por lo tanto, es en sí mismo una violación del NDA. Debería escribir algo como "No es posible comentar sobre lo que hay en [próxima versión] sin romper el NDA".
hatfinch
Además, si se encuentra escribiendo muchas cadenas atribuidas, consulte esta publicación / categoría. Facilita un poco la creación. raizlabs.com/dev/2014/03/nsattributedstring-creation-helpers
Alex Rouse
15

Debería probar TTTAttributedLabel . Es un reemplazo directo de UILabel que funciona con NSAttributedString y tiene el rendimiento suficiente para UITableViewCells.

mattt
fuente
Esta clase se encuentra en la biblioteca Three20 que se menciona a continuación.
David H
10
No, esto no es de Three20 (observe las 3 Ts)
vikingosegundo
6

¿Hay alguna forma sencilla como

NSAttributedString * str;

UILabel * etiqueta;

label.attributedString = str;

Casi. Solo use un CATextLayer. Tiene una stringpropiedad que puede establecer en NSAttributedString.

EDITAR (noviembre de 2012): Por supuesto, todo esto ha cambiado en iOS 6. En iOS 6, puede hacer exactamente lo que pidió el OP: asignar una cadena atribuida directamente a una etiqueta attributedText.

mate
fuente
1
¿Podría ser más específico, por ejemplo, proporcionar un ejemplo de uso?
William Niu
1
Sí, se llama mi libro, Programación iOS 5. Aquí está el ejemplo de código del libro: github.com/mattneub/Programming-iOS-Book-Examples/blob/master/...
mate
6

Respuesta para la alineación de texto atribuida por UILabel en iOS 6: use NSMutableAttributedString y agregue NSMutableParagraphStyle al atributo. Algo como esto:

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
fuente
6

Pensé que sería útil dar un ejemplo de análisis de una cadena HTML (simplificada) para crear una NSAttributedString.

No está completo, solo maneja las etiquetas <b> y <i>, para empezar, y no se molesta con el manejo de errores, pero es de esperar que también sea un ejemplo útil de cómo comenzar con 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


Para usar, haga algo como esto:


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

Pete
fuente
5

A partir de iOS 6.0 puedes hacerlo así: otro código de muestra.

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
fuente
2

Para Swift usa esto,

Hará que los textos de Titl estén en negrita,

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
fuente
2

Sé que es un poco tarde, pero será útil para otros

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

[self.label setAttributedText:newString];

Agregue el atributo deseado al diccionario y páselo como parámetro de atributos

satheesh
fuente