2012-01-20 21 views
1

我正在尋找一個測量字符串高度的程序,並且我發現這個問題在另一個堆棧溢出問題上。它適用於我的NSTableViewColumns有Word換行作爲換行符 我的問題是,如果我將換行符更改爲字符換行,如何更新此代碼?在Cocoa中測量字符串高度

- (NSSize)sizeForWidth:(float)width 
       height:(float)height { 
    NSSize answer = NSZeroSize ; 
    gNSStringGeometricsTypesetterBehavior = NSTypesetterBehavior_10_2_WithCompatibility; 
    if ([self length] > 0) { 
     // Checking for empty string is necessary since Layout Manager will give the nominal 
     // height of one line if length is 0. Our API specifies 0.0 for an empty string. 
     NSSize size = NSMakeSize(width, height) ; 
     NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize:size] ; 
     NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:self] ; 
     NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init] ; 
     [layoutManager addTextContainer:textContainer] ; 
     [textStorage addLayoutManager:layoutManager] ; 
     [layoutManager setHyphenationFactor:0.0] ; 
     if (gNSStringGeometricsTypesetterBehavior != NSTypesetterLatestBehavior) { 
      [layoutManager setTypesetterBehavior:gNSStringGeometricsTypesetterBehavior] ; 
     } 
     // NSLayoutManager is lazy, so we need the following kludge to force layout: 
     [layoutManager glyphRangeForTextContainer:textContainer] ; 

     answer = [layoutManager usedRectForTextContainer:textContainer].size ; 
     [textStorage release] ; 
     [textContainer release] ; 
     [layoutManager release] ; 

     // In case we changed it above, set typesetterBehavior back 
     // to the default value. 
     gNSStringGeometricsTypesetterBehavior = NSTypesetterLatestBehavior ; 
    } 

    return answer ; 
} 

回答

2

這種感覺就像你重塑[NSAttributedString boundingRectWithSize:options:](或只是size)。我在執行中遺漏了什麼? NSLayoutManager用於處理快速變化的字符串(如在文本視圖中)。大多數時候它是過度殺傷。你有意繞過它的優化(在你的行中注意到NSLayoutManager是懶惰的,你的意思是優化:D)

在任何一種情況下,要改變包裝行爲,你需要修改NSAttributedString本身。包裝是paragraph style的一部分。像這樣的東西(未經測試,可能無法進行編譯):

// Lazy here. I'm assuming the entire string has the same style 
NSMutableParagraphStyle *style = [[self attribute:NSParagraphStyleAttributeName atIndex:0 effectiveRange:NULL] mutableCopy]; 
[style setLineBreakMode:NSLineBreakByCharWrapping]; 
NSAttributedString *charWrappedString = [self mutableCopy]; 
[charWrappedString setAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, [self length]]; 

NSRect boundingRect = [self boundingRectWithSize:NSMakeSize(width, height) options:0]; 
NSSize size = boundRect.size; 

[style release]; 
[charWrappedString release]; 

return size; 

風格是有點棘手,因爲他們包括他們幾件事情,但你必須設置它們放在一起。因此,如果屬性字符串中有不同的樣式,則必須遍歷字符串,處理每個effectiveRange。 (您想閱讀文檔以瞭解attributesAtIndex:effectiveRange:attributesAtIndex:longestEffectiveRange:inRange:之間的權衡。)

+0

感謝您的回覆,即使使用段落樣式,boundingRectWithSize也會返回單行大小的矩形,可能會出現什麼錯誤? –

+0

你在選項中包含了'NSStringDrawingUsesLineFragmentOrigin'標誌嗎? – trss

+0

謝謝! NSStringDrawingUsesLineFragmentOrigin正在爲我工​​作! –