2013-09-23 31 views
5

Wiele metod, których używałem do określenia układu drukowanych ciągów do tworzenia złożonych dokumentów PDF, zostało wycofanych w iOS7. Dokumentacja wywołuje tę samą metodę, aby użyć go jako zamiennik dla wszystkich metod sizeWithFont które są nieaktualne:Zamiennik dla sizeWithFont: ForWidth: lineBreakMode:

boundingRectWithSize:options:attributes: 

To dobrze dla sizeWithFont:ConstrainedTosize:lineBreakMode ale co zrobić, jeśli chcę mój ciąg tylko na jednej linii? Nie wiem, co używać w przypadku maksymalnej wysokości, więc nie mam parametru "rect to przekazać" jako wartości pierwszego parametru.

Oto, co mam, ograniczając do danego rozmiaru.

CGFloat maxHeightAllowable = _maxHeight; 
CGSize issueTitleMaxSize = CGSizeMake(_issueListTitleColWidth - (kColumnMargin *2), maxHeightAllowable); 
NSDictionary *issueTitleAttributes = [NSDictionary dictionaryWithObjectsAndKeys:_bodyFont, NSFontAttributeName, nil]; 
CGRect issueTitleRect = CGRectIntegral([issueTitleText boundingRectWithSize:issueTitleMaxSize options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:issueTitleAttributes context:nil]); 
CGSize issueTitleSize = issueTitleRect.size; 

Jak bym stosować tę samą metodę, jeśli ja nie wiem maxheight, czy rzeczywiście, wysokość na jednej linii jest dokładnie to, co staram się dowiedzieć?

Widzę, dlaczego naciskają na kompatybilność łańcuchów NSAttributed i automatyczny układ, ale dlaczego je przestają? Zamiennik, w moim przypadku, teraz zajmuje 4 lub 5 kroków, gdzie był 1 lub 2.

Stosując właściwość lineHeight fontu, zgodnie z sugestią pana T, zrobiłem te metody w kategorii, która znacznie upraszcza moje zastąpienie.

#import "NSString+SizingForPDF.h" 

@implementation NSString (SizingForPDF) 

-(CGSize)integralSizeWithFont:(UIFont *)font constrainedToSize:(CGSize)maxSize 
{ 
    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil]; 
    CGRect rect = CGRectIntegral([self boundingRectWithSize:maxSize options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:attributes context:nil]); 
    return rect.size; 
} 

-(CGSize)integralSizeWithFont:(UIFont *)font maxWidth:(CGFloat)maxWidth numberOfLines:(NSInteger)lines 
{ 
    if (lines == 0) { 
     lines = 1; 
    } 
    NSDictionary *attributes = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName]; 
    CGFloat height = font.lineHeight * lines; 
    CGSize maxsize = CGSizeMake(maxWidth, height); 
    CGRect rect = CGRectIntegral([self boundingRectWithSize:maxsize options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesFontLeading attributes:attributes context:nil]); 
    return rect.size; 
} 

@end 

Odpowiedz

15

Jeśli po prostu patrząc na wysokości jednej linii, nie może po prostu użyć czcionkę za lineHeight nieruchomość? Używam tego, aby ustawić wysokość moich etykiet lub odpowiednio przewidzieć wysokość elementów bez żadnych problemów. Nie jestem pewien, czy dokumenty PDF różnią się pod tym względem.

Co więcej, uważam, że te funkcje zostały uznane za przestarzałe, ponieważ ta seria funkcji NSString + UIKit (sizeWithFont:... itd.) Opierała się na bibliotece UIStringDrawing, która nie była bezpieczna dla wątków. Jeśli spróbujesz uruchomić je nie w głównym wątku (jak w przypadku innych funkcji UIKit), dostaniesz nieprzewidywalne zachowania. W szczególności, jeśli uruchomisz funkcję na wielu wątkach jednocześnie, prawdopodobnie spowoduje to awarię aplikacji. Dlatego w iOS 6 wprowadzono metodę NSAttributedStrings w postaci boundingRectWithSize:.... Zostało to zbudowane na bibliotekach NSStringDrawing i jest bezpieczne dla wątków.

W tej notatce, jeśli wspierałeś tylko iOS 6 i iOS 7, zdecydowanie zmieniłbym wszystkie twoje NSString na sizeWithFont:... na NSAttributeString's boundingRectWithSize. To pozwoli Ci zaoszczędzić wiele bólu głowy, jeśli masz dziwną, wielowątkową skrzynkę narożną! Oto jak ja konwertowane NSString na sizeWithFont:constrainedToSize::

Co kiedyś:

NSString *text = ...; 
CGFloat width = ...; 
UIFont *font = ...; 
CGSize size = [text sizeWithFont:font 
       constrainedToSize:(CGSize){width, CGFLOAT_MAX}]; 

można łatwo wymienić z:

NSString *text = ...; 
CGFloat width = ...; 
UIFont *font = ...; 
NSAttributedString *attributedText = 
    [[NSAttributedString alloc] 
     initWithString:text 
     attributes:@ 
     { 
      NSFontAttributeName: font 
     }]; 
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX} 
              options:NSStringDrawingUsesLineFragmentOrigin 
              context:nil]; 
CGSize size = rect.size; 

Uwaga dokumentacji wspomina:

w iOS 7 i później ta metoda zwraca rozmiary ułamkowe (w rozmiarze składnik zwrotu ed CGRect); aby użyć wymiarów o rozmiarze zwróconym do rozmiaru , należy użyć jego wartości do najbliższej większej liczby całkowitej za pomocą funkcji ceil.

więc wyciągnąć wysokość obliczoną lub szerokość ma być używany do zaklejania widoki, chciałbym używać:

CGFloat height = ceilf(size.height); 
CGFloat width = ceilf(size.width); 
+0

Twoja metoda jest prawie taki sam jak mój, tylko używam makra CGRectIntegral do zaciskania wartości do liczb całkowitych. Nigdy nie myślałem, aby spojrzeć na czcionkę dla wysokości linii. To była odpowiedź dla mnie. Użyłem go do stworzenia kilku nowych metod w kategorii, która łatwiej zastąpi mój poprzedni kod. –

+1

LineBreakMode zastępuje się atrybutem NSParagraphStyle, który można dodać do słownika atrybutów. Zobacz http://stackoverflow.com/a/26894770/338468 dla szczegółowego przykładu, jak to zrobić. –

Powiązane problemy