Re: attributesAtIndex:effectiveRange: vs the insertion point at end of text
Re: attributesAtIndex:effectiveRange: vs the insertion point at end of text
- Subject: Re: attributesAtIndex:effectiveRange: vs the insertion point at end of text
- From: Douglas Davidson <email@hidden>
- Date: Wed, 18 Sep 2002 12:18:11 -0700
On Tuesday, September 17, 2002, at 09:36 PM, Kirk Kerekes wrote:
I am trying to provide some simple Carbon-style text attribute control
in my Cocoa app. As part of this, I need to determine the current text
attributes of the selection in a NSTextView.
Which appears to work just dandy except if I click at the end of the
text in the NSTextView. Then I get exceptions like:
-[NSMutableRLEArray objectAtIndex:effectiveRange:]
"'NSInternalInconsistencyException'
(reason 'Access invalid attribute location 6 (length 6)')"
It seems that attributesAtIndex:effectiveRange: is unhappy with the
seemingly valid notion of an attributed insertion point at the end of
text -- and yet the standard Font and Text menu items don't have this
problem. The error message is bizarre also -- how can an insertion
point imply a range with a "(length 6)"
The insertion point has to have attributes, so that they can be
applied to the next typed character. It seems doltish to have to
special-case this extremely _common_ case.
Let me explain the model in use here. The NSTextStorage is a subclass
of NSMutableAttributedString. The model used by NSAttributedString is
that of a string with a dictionary of attributes attached to each
character. As with NSString, if you attempt to refer to a character
index beyond the end of the string, you raise an exception. In this
case, you are asking an NSAttributedString of length 6 for the
attributes associated with the character at index 6--but there is no
character at index 6, since the indexes of the 6 characters range from
0 to 5. The notation "(length 6)" means that the length of the string
is 6. You will notice that the length of the selected range plays no
role here, since the arguments to this particular method include only
the selected range's location.
There certainly are attributes that will be applied to the next typed
character, but we do not consider them as being attributes of the
insertion point. The NSTextView keeps track of them, and calls them
(naturally enough) the typingAttributes. Ordinarily the
typingAttributes start out being derived from the attributes of the
character before the selected range (i.e., the character at index
selectedRange.location - 1) but they do not always stay that way. For
example, if there is a zero-length selection and the user selects
"bold" then it is the typing attributes that change rather than the
attributes of any character. Also, there are typing attributes even if
there are no characters to have attributes--for example, if the text is
empty.
In model-view-controller terms, the text storage is part of the model,
and the text view is part of the view. It would be inappropriate for
the typing attributes to be stored with the text storage, because they
depend on user actions (like "bold") that may not necessarily be
associated with any change in the underlying model. Hence the typing
attributes are associated with the view object, the NSTextView. That
is why you do not get them by querying the model object, the
NSTextStorage.
Douglas Davidson
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.