使用属性文本在UITextView中重绘NSTextAttachments

时间:2014-07-01 11:54:35

标签: ios uitextview nstextattachment

我有一个NSTextAttachment子类,覆盖了attachmentBoundsForTextContainer:proposedLineFragment:glyphPosition:characterIndex:
imageForBounds:textContainer:characterIndex:

我需要在某些时候重新绘制附件。在UITextView上调用setNeedsDisplay并不起作用。

有什么想法吗?我想避免重新创建附件和/或属性字符串。

3 个答案:

答案 0 :(得分:16)

您希望使用textView.layoutManager方法之一。

  • invalidateDisplayCharacterRange:
    • imageForBounds:textContainer:characterIndex:将再次被召唤。
    • attachmentBoundsForTextContainer:[...]Index:不再再次调用。
    • 如果使用相同尺寸中的另一个更改了image,则效果很好。
  • invalidateLayoutForCharacterRange:actualCharacterRange:
    • imageForBounds:textContainer:characterIndex:将再次被召唤。
    • attachmentBoundsForTextContainer:[...]Index:将再次被召唤。
    • 如果image已使用另一个不同尺寸更改,则表现良好。

如果您只想更新单个附件,您可能会发现我写的这个帮助方法很有帮助:

- (NSRange)rangeOfAttachment:(NSTextAttachment *)attachment {
    __block NSRange ret;
    [self.textStorage enumerateAttribute:NSAttachmentAttributeName
                                 inRange:NSMakeRange(0, self.textStorage.length)
                                 options:0
                              usingBlock:^(id value, NSRange range, BOOL *stop) {
                                  if (attachment == value) {
                                      ret = range;
                                      *stop = YES;
                                  }
                              }];
    return ret;
}

您可以将此方法的结果NSRange传递给这些invalidate方法中的任何一个的第一个参数。对于第二种方法的actualCharacterRange:参数,我已经传递了NULL而没有任何问题。

答案 1 :(得分:3)

嗯,经过一些挖掘,可以通过使布局管理器失效来完成:

[textView.layoutManager invalidate....]

Apple docs

答案 2 :(得分:-1)

如果您只想更改图像初始化的NSTextAttachment,建议您使用

setAttachmentSize:size forGlyphRange:range