2013-09-23 3 views
5

Многие методы, которые я использовал для определения макета печатных строк для создания сложных PDF-документов, были устаревшими в iOS7. Документация взывает тот же метод, чтобы использовать в качестве замены для всех методов sizeWithFont, которые устаревшее:Замена для sizeWithFont: ForWidth: lineBreakMode:

boundingRectWithSize:options:attributes: 

Это нормально для sizeWithFont:ConstrainedTosize:lineBreakMode но что, если я хочу, чтобы моя строка только на одной строке? Я не знаю, что использовать для максимальной высоты, поэтому у меня нет прямого выражения в качестве значения для первого параметра.

Вот что я имею, ограничивая данный размер.

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; 

Как бы использовать этот же метод, если я не знаю MaxHeight, или на самом деле, высота одной линии именно то, что я пытаюсь выяснить?

Я понимаю, почему они стремятся к совместимости с строками NSAttributed и автоматической компоновкой, но зачем их осуждать? Замена, в моем случае, теперь занимает 4 или 5 шагов, когда она была 1 или 2.

Используя свойство fontHeight шрифта, как предложил г-н Т., я сделал эти методы в категории, которая значительно упрощает мои замена.

#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 

ответ

15

Если вы просто ищете высоту одной строки, вы не могли бы просто использовать lineHeight свойства вашего шрифта? Я использую это, чтобы установить высоту моих меток или правильно предвидеть высоту элементов без каких-либо проблем. Я не уверен, что документы PDF отличаются в этом отношении.

Кроме того, я считаю, что эти функции были устаревшими, потому что эта серия функций NSString + UIKit (sizeWithFont:... и т. Д.) Была основана на библиотеке UIStringDrawing, которая не была потокобезопасной. Если вы попытались запустить их не в основном потоке (как и любая другая функция UIKit), вы получите непредсказуемое поведение. В частности, если вы запускаете функцию на нескольких потоках одновременно, это, вероятно, приведет к краху вашего приложения. Вот почему в iOS 6 они ввели метод boundingRectWithSize:... для NSAttributedStrings. Это было построено поверх библиотек NSStringDrawing и является потокобезопасным.

На этой ноте, если бы вы поддерживали только iOS 6 и iOS 7, то я определенно изменил бы все ваши NSString sizeWithFont:... на NSAttributeString boundingRectWithSize. Это сэкономит вам много головной боли, если у вас будет странный многопоточный угловой футляр! Вот как я преобразовал NSString-х sizeWithFont:constrainedToSize::

Что раньше:

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

Может быть легко заменен:

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; 

Обратите внимание на документацию упоминает:

В прошивке 7 и более поздних версий, этот метод возвращает дробные размеры (в размере компонент возврата ed CGRect); чтобы использовать возвращаемый размер в размере просмотров, вы должны использовать поднимите его значение до ближайшего высшего целого , используя функцию ceil.

Так вытащить расчетную высоту или ширину, которая будет использоваться для калибровки точки зрения, я хотел бы использовать:

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

Ваш метод почти так же, как у меня, только я использую макрос CGRectIntegral зажать значения для целых чисел. Я никогда не думал о шрифте для высоты линии. Это был ответ для меня. Я использовал его для создания нескольких новых методов в категории, которые легче заменяют мой прежний код. –

+1

LineBreakMode заменяется атрибутом NSParagraphStyle, который можно добавить в словарь атрибутов. См. Http://stackoverflow.com/a/26894770/338468 для подробного примера того, как это сделать. –

Смежные вопросы