Maintaining an ordered array of attributes in an NSTextStorage subclass
Maintaining an ordered array of attributes in an NSTextStorage subclass
- Subject: Maintaining an ordered array of attributes in an NSTextStorage subclass
- From: Keith Blount <email@hidden>
- Date: Mon, 10 Aug 2009 05:55:08 -0700 (PDT)
Hello,
I'm trying to implement comments in an NSTextStorage subclass. The implementation of comments themselves is pretty simple:
- I have a KBCommentsAttributeName custom attribute that gets assigned to ranges of text in my controller using the -addAttribute:value:range: methods.
- This attribute gets assigned a dictionary containing an attributed string (the comment) and a unique ID (because NSAttributedString optimises things by merging attributes that are the same, and I want to avoid this).
So, for instance, a comment might be assigned in my controller like this:
- (void)addComment:(id)sender
{
if ([textView shouldChangeTextInRange:[textView rangeForUserAttributeChange] replacementString:nil])
{
NSDictionary *commentDict = [NSDictionary dictionaryWithObjectsAndKeys:[commentsTextView textStorage], @"Comment", uniqueID, @ID", nil];
[[textView textStorage] addAttribute:KBCommentAttributeName value:commentDict range:[textView rangeForUserAttributeChange];
[textView didChangeText];
}
}
(The above just typed in my browser as an example.)
This is all fine. However, what I would like to do is have the text storage to which this attribute is assigned maintain an ordered array of the comments that get assigned. In other words, my NSTextStorage subclass should have a method,
- (NSMutableArray *)comments;
which returns all of the comment objects (dictionary objects in the example above) that are in the text, in the order they appear.
(The reason I want this is so that I can then show all of the comments in a separate view.)
Obviously, I could just get all of the comments associated with the text dynamically using the attribute-searching methods such as -attribute:atIndex:range:effectiveRange: etc, but this doesn't suit my purpose. My comments-showing view needs to be notified whenever the comment ranges change or whenever a comment is deleted or added; calling the -attribute: searching methods on the entire text every time the text is changed would be way too slow.
One thought I had was to create a -fixCommentsInRange: method and call it from -fixAttributesInRange:, but fixing up the comments ranges is fundamentally different from the other attribute fixing methods (such as fixParagraph... or fixFontAttribute...), because the other attributes-fixing methods don't need to know about the rest of the text and only need to scan over the current paragraph at most. To ensure that my -comments mutable array contained all of the comments in the text, it would pretty much have to search through all of the text from the beginning of the range passed into -fixCommentsInRange: to the end of the text, which would be too slow. (Because calling something from -fixAttributesInRange: would give us no information about whether a comment has just been deleted or added; it will only tell us what is at the range at the moment.)
My current thinking is that the best way of doing this will be to handle it in NSTextStorage overrides for -addAttribute:value:range:, -setAttributes:range:, and -removeAttribute:..., where I can check if the attribute is being removed or added, but even then it gets a little complicated in trying to account for copying and pasting and so forth.
Has anyone handled anything like this, or does anyone have any better ideas as to how I might approach this? As I say, the aim is to maintain a list of the comment attributes in the text just so that I can display the comments, in order, in a custom view that will keep updated with the text.
Many thanks in advance and all the best,
Keith
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden