2017-01-13 12 views
1

У меня есть UITextView с некоторым атрибутом текста, где установлен textContainer.maximumNumberOfLine (в данном случае 3).UITextView: Найти местоположение многоточия в усеченном тексте

Я хотел бы найти индекс символа многоточия в диапазоне символов атрибутивной строки.

например:

Оригинал Строка:

"Lorem ipsum dolor sit amet, consectetur adipiscing elit"

Строка, как показано, после усечения:

Lorem ipsum dolor sit amet, consectetur...

Как определить индекс ...?

ответ

2

Вот функция расширения NSAttributedString, которая выполняет задание. Работает для одного & многострочный текст.

Это заняло у меня всего около 8 часов, чтобы выяснить, так что я думал, что я отправлю его в качестве Q & А.

(Swift 2.2)

/** 
    Returns the index of the ellipsis, if this attributed string is truncated, or NSNotFound otherwise. 
*/ 
func truncationIndex(maximumNumberOfLines: Int, width: CGFloat) -> Int { 

    //Create a dummy text container, used for measuring & laying out the text.. 

    let textContainer = NSTextContainer(size: CGSize(width: width, height: CGFloat.max)) 
    textContainer.maximumNumberOfLines = maximumNumberOfLines 
    textContainer.lineBreakMode = NSLineBreakMode.ByTruncatingTail 

    let layoutManager = NSLayoutManager() 
    layoutManager.addTextContainer(textContainer) 

    let textStorage = NSTextStorage(attributedString: self) 
    textStorage.addLayoutManager(layoutManager) 

    //Determine the range of all Glpyhs within the string 

    var glyphRange = NSRange() 
    layoutManager.glyphRangeForCharacterRange(NSMakeRange(0, self.length), actualCharacterRange: &glyphRange) 

    var truncationIndex = NSNotFound 

    //Iterate over each 'line fragment' (each line as it's presented, according to your `textContainer.lineBreakMode`) 
    var i = 0 
    layoutManager.enumerateLineFragmentsForGlyphRange(glyphRange) { (rect, usedRect, textContainer, glyphRange, stop) in 
     if (i == maximumNumberOfLines - 1) { 

      //We're now looking at the last visible line (the one at which text will be truncated) 

      let lineFragmentTruncatedGlyphIndex = glyphRange.location 
      if lineFragmentTruncatedGlyphIndex != NSNotFound { 
       truncationIndex = layoutManager.truncatedGlyphRangeInLineFragmentForGlyphAtIndex(lineFragmentTruncatedGlyphIndex).location 
      } 
      stop.memory = true 
     } 
     i += 1 
    } 

    return truncationIndex 
} 

Обратите внимание, что это не имеет были проверены за некоторыми простыми случаями. Там могут быть краевые случаи, требующие некоторых корректировок.

+0

Очень хороший подход – greenisus