iphone / ipad: Jak dokładnie używać NSAttributedString?

102

Tak, wiele osób mówi o Rich Text na iPhonie / iPadzie i wielu o tym wie NSAttributedString.

Ale jak używać NSAttributedString? Szukałem przez długi czas, żadnych wskazówek dotyczących ekstrakcji.

Wiem, jak skonfigurować NSAttributedString, to co powinienem zrobić, aby wyświetlić tekst na iPhonie / iPadzie z tekstem sformatowanym?

Oficjalna dokumentacja mówi, że należy go używać CoreText.Framework, co to oznacza?

Czy istnieje taki prosty sposób?

NSAttributedString *str;
.....
UILabel *label;
label.attributedString = str;
Jacek
źródło
Powyższa odpowiedź jest jednak prawidłowa. Koduj w ten sposób i upewnij się, że dodajesz strukturę CoreText do połączonych struktur.
mxcl
Dzięki, poprawną odpowiedź zostawiłem Wesowi
Jackowi
Three20 ooks jak całkiem imponująca biblioteka: github.com/facebook/three20
David H,
87
Three20 to bzdura.
bandejapaisa
4
To irytujące, ale nie sądzę, żeby to było gorsze. Przez ostatnie 6 miesięcy prowadziłem projekt, który wykorzystuje Three20 ... niektóre rzeczy, które robią z pamięcią, wprawiają mnie w zakłopotanie. Kod jest naprawdę delikatny, ponieważ nie obsługuje pamięci w ortodoksyjny sposób. O wiele lepiej jest robić to, co sami zapewniają. Jest mało prawdopodobne, że będziesz potrzebować wszystkiego, co zapewniają. Zrób to sam ... dowiesz się więcej, będzie fajniej, pewnie zrobisz to lepiej!
bandejapaisa

Odpowiedzi:

79

Powinieneś spojrzeć na OHAttributedLabel AliSoftware . Jest to podklasa UILabel, która rysuje NSAttributedString, a także zapewnia wygodne metody ustawiania atrybutów NSAttributedString z klas UIKit.

Z próbki dostarczonej w repozytorium:

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

Uwaga: w iOS 6+ możesz renderować ciągi z przypisanymi atrybutami za pomocą właściwości attributeText z UILabel.

Wes
źródło
Nie ma czegoś takiego jak UIAttributedLabel. Myślę, że masz na myśli OHAttributedLabel.
Erik B
5
Został przemianowany na OHAttributedLabel w zatwierdzeniu w listopadzie 2010 . Zaktualizowałem odpowiedź.
Wes
1
Dziękuję Wes! Ty i Olivier Halligon, który napisał kod! Dziękuję Ci!
DenNukem
1
Dzięki @Wes za wspomnienie o mojej klasie i dzięki @DenNukem za kredyty ... Nie wiedziałem, że jest tak sławny;) W każdym razie, zrobiłem wiele aktualizacji i poprawek na tej klasie od czasu oryginalnego postu, więc nie rób tego nie zapomnij o ściągnięciu repozytorium github!
AliSoftware
Otrzymuję błąd w każdym wierszu twojego kodu. Zgodnie z dokumentacją
żadna
155

Począwszy od iOS 6.0 możesz to zrobić tak:

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
źródło
60
Pierwsza zasada programu deweloperskiego na iOS to nie mówić o programie deweloperskim na iOS.
Jeremy Moyers
5
Druga zasada programu deweloperskiego iOS to ... zobacz pierwszą regułę.
futureelite7
32
Stwierdzenie, że ktoś naruszył NDA, oznacza potwierdzenie, że przedstawiony materiał rzeczywiście jest w systemie iOS6, a zatem samo w sobie stanowi naruszenie NDA. Powinieneś napisać coś w stylu „Nie można komentować tego, co jest w [nadchodzącej wersji] bez zerwania umowy NDA”.
hatfinch
Również jeśli zauważysz, że piszesz wiele przypisywanych ciągów, sprawdź ten post / kategorię. Ułatwia tworzenie. raizlabs.com/dev/2014/03/nsattributedstring-creation-helpers
Alex Rouse
15

Powinieneś spróbować TTTAttributedLabel . Jest to zamiennik typu drop-in dla UILabel, który działa z NSAttributedString i jest wystarczająco wydajny dla UITableViewCells.

mattt
źródło
Ta klasa znajduje się we wspomnianej poniżej bibliotece Three20.
David H,
10
Nie, to nie jest z trzech20 (zwróć uwagę na 3 Ts)
vikingosegundo
6

Czy są jakieś proste sposoby, na przykład

NSAttributedString * str;

Etykieta UILabel *;

label.attributedString = str;

Prawie. Po prostu użyj CATextLayer. Ma stringwłaściwość, którą można ustawić na NSAttributedString.

EDYCJA (listopad 2012): Oczywiście wszystko to uległo zmianie w iOS 6. W iOS 6 możesz zrobić dokładnie to, o co prosił OP - przypisać przypisany ciąg bezpośrednio do etykiety attributedText.

matowe
źródło
1
Czy mógłbyś podać bardziej szczegółowe informacje, np. Podać przykładowe użycie?
William Niu,
1
Tak, nazywa się moja książka, Programowanie iOS 5. Oto przykładowy kod z książki: github.com/mattneub/Programming-iOS-Book-Examples/blob/master/ ...
mat
6

Odpowiedź na wyrównanie tekstu z przypisanym atrybutem UILabel w systemie iOS 6: użyj NSMutableAttributedString i dodaj NSMutableParagraphStyle do atrybutu. Coś takiego:

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
źródło
6

Pomyślałem, że przydałoby się podanie przykładu parsowania (uproszczonego) ciągu HTML, aby utworzyć NSAttributedString.

Nie jest kompletny - na początek obsługuje tylko tagi <b> i <i> i nie zawraca sobie głowy obsługą błędów - ale mam nadzieję, że jest również użytecznym przykładem, jak rozpocząć pracę z 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


Aby użyć, zrób coś takiego:


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

Pete
źródło
5

Począwszy od iOS 6.0 możesz to zrobić w ten sposób: kolejny przykładowy kod.

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
źródło
2

Dla Swift użyj tego,

Dzięki temu teksty tytułów będą pogrubione,

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
źródło
2

Wiem, że jest trochę za późno, ale przyda się innym,

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

[self.label setAttributedText:newString];

Dodaj żądany atrybut do słownika i przekaż go jako parametr atrybutów

satheesh
źródło