2

I have a textview which contains multiple paragraphs. Each string can be formatted differently, for example some strings are bold and others using italicized fonts.

How would I get the attributes for a specific substring and get the attributes for the substring before that one?

For example I want to get the attributes for the selected text as well as the text that is displayed before it.

Here is what I have so far.

let range: UITextRange = textView.selectedTextRange!
let selectedText = textTV.text(in: range)
let previousRange: UITextRange = textView.textRange(from: textView.beginningOfDocument, to: range.start)!
let previousText = textTV.text(in: previousRange)

With this I was able to get the string that was selected by the user. As well as the text behind it.

However I don't know how to rip the attributes of that string out.

mocode10
  • 589
  • 1
  • 6
  • 23
  • Use the text view's `attributedText` property. – rmaddy Jun 22 '17 at 21:17
  • This would return the attributed text for the whole textview wouldn't it? I need to get multiple attributed text properties as each string can have it's own attributes that differ from each other. – mocode10 Jun 22 '17 at 21:27
  • You can then use `attributedSubstring` to get a desired portion. – rmaddy Jun 22 '17 at 21:30

2 Answers2

3

You can enumerate attributes and apply them for the new text:

textView.attributedText.enumerateAttributes(in: textView.selectedRange, options: .longestEffectiveRangeNotRequired) { (attributes, range, stop) in
    // do what you need
}

Description:

Executes the block for each attribute in the range. If this method is sent to an instance of NSMutableAttributedString, mutation (deletion, addition, or change) is allowed, as long as it is within the range provided to the block; after a mutation, the enumeration continues with the range immediately following the processed range, after the length of the processed range is adjusted for the mutation. (The enumerator basically assumes any change in length occurs in the specified range.) For example, if block is called with a range starting at location N, and the block deletes all the characters in the supplied range, the next call will also pass N as the index of the range.

Vasilii Muravev
  • 3,063
  • 17
  • 45
1

If you are simply looking for an attributed text for a given range, and you have a subclass of NSLayoutManager, you can call textStorage.attributedSubstring(from: glyphRange). The glyphRange here comes from enumerateLineFragments method called from the subclass of NSLayoutManager.

Just putting it out there in case anyone needs this!

Joseph Francis
  • 1,111
  • 1
  • 15
  • 26