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;

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.


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;

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.


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.


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;

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


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;

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

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.