问题
I have a NSTextAttachment subclass with overridden attachmentBoundsForTextContainer:proposedLineFragment:glyphPosition:characterIndex:
imageForBounds:textContainer:characterIndex:
.
I need to redraw the attachment(s) at some point. Calling setNeedsDisplay
on the UITextView doesn't work.
Any ideas? I'd like to avoid recreating attachments and/or the attributed string.
回答1:
You'll want to use one of textView.layoutManager
's methods.
invalidateDisplayCharacterRange:
imageForBounds:textContainer:characterIndex:
will be called again.attachmentBoundsForTextContainer:[...]Index:
will not be called again.- Good if the
image
has been changed with another one of the same size.
invalidateLayoutForCharacterRange:actualCharacterRange:
imageForBounds:textContainer:characterIndex:
will be called again.attachmentBoundsForTextContainer:[...]Index:
will be called again.- Good if the
image
has been changed with another one of a different size.
If you just want to update a single attachment, you may find this helper method I wrote helpful:
- (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;
}
You can pass the resulting NSRange
of this method to the first argument of either of those invalidate
methods. For the actualCharacterRange:
argument of the second method, I've been passing in NULL
without any problems.
回答2:
Well, after some digging, that can done by invalidating the layout manager:
[textView.layoutManager invalidate....]
Apple docs
回答3:
If you just want to change the NSTextAttachment which is init by a image, I suggest you to use
setAttachmentSize:size forGlyphRange:range
来源:https://stackoverflow.com/questions/24509660/redrawing-nstextattachments-in-an-uitextview-with-attributed-text