I hope people aren't getting discouraged as they read this thread. Yes,
the Yellow Box text system is quite complex if you want to learn the
whole thing. However, most people don't have to learn the whole thing
and we have tried very hard to make it simple to do simple things while
keeping it possible to do really advanced and tricky things.
Also, some of the confusion in this discussion has arisen from the fact
that many people had come to know certain idioms and usage patterns of
the older class NSCStringText which the new text system replaces. In
some cases, trying to apply those old patterns to the new classes makes
things seem more difficult and complicated thanb they really are. For
instance, with the old system you really had to set a selection in order
to remove or replace text. This is no longer tru, and in fact, you
shouldn't change the selection in order to make programmatic changes
(like appending text).
So, if you're reading all this and thinking it sounds confusing, don't
despair. Chances are you won't have to deal with a lot of these issues.
Now, on to muddy the waters further. :-)
Shouldn't this be a category on NSText but with [[self string] length]
used to find the string length? When a
text object in a scroll view is pulled off of the IB DataViews palette,
if the text object is configured not to
accept multiple fonts, the text object created at run-time is an
NSCStringText, not an NSTextView object,
despite the IB inspector being named "NSTextView Inspector". If you
then send appendString: defined in
the above category to this text object, you'll get an unimplemented
message error which can be very
confusing. In fact, if you invoke any method defined in NSTextView to
this text object, a run-time error
will occur.
It should NOT be the case that you can ever get an NSCStringText off the
palette in IB. If it is, it's a bug. Please report it, if this is
happening to you. It should not matter whether you configure it for
rich text or not.
Also, I recommend never using an NSCStringText object unless you
absolutely have to. This is, for the most part, an obsolete class (just
look at its nasty name :-).
NSText exists purely for OpenStep-spec reasons. It is not that
important anymore in my opinion. It was there to define a common subset
API between the old NSCStringText and the new text system. The idea was
that an OpenStep app that used NSText exclusively would get an
NSCStringText on OpenStep implementations that did not include the new
text system, but would get the new stuff if it was there. The NSText
API is really pretty minimal though, and any sophisticated app is going
to eventually want to use API specific to the new text system (or the
old one...)
Does this apply to attributes changes as well? I change the text color
attribute in
textView:willChangeSelectionFromCharacterRange:toCharacterRange: and
the color change appears
immediately without sending scrollRangeToVisible: (well, the text that
is visible changes color
immediately anyway :-)
NSLayoutManager is lazy. It will, eventually, get around to laying out
and causing the display of any changes to the backing store. But
without a specific reason to do so, it will do it in the background when
it gets a chance.
You can always force layout to occur synchronously by asking the
NSLayoutManager a question that requires layout to be done up to a
certain point in order to get an answer. The reason that
-scrollRangeToVisible: will cause layout to be done immediately is
because it must ask the NSLayoutManager where in the view the range lies
and to answer, NSLayoutManager will have to have current layout
information at least up to the end of the range.
Any change initiated from the UI will cause synchronous layout up to at
least the end of the selection, and will therefore cause the immediate
display of the new layout up to that point. This is because the
user-action type methods in NSTextView are implemented to do that
explicitly.
When you change the color in your selection change notification handler,
if your change occurs in the range of the old or new selection, it will
get laid out and displayed as a side effect of the fact that when the
selection changes the NSTextView wants to ensure the redisplay of the
new selection. Or if you're changing attributes on a range downstream
from the selection change activity it could be that the background
layout happens quickly enough that it looks like its synchronous.
If you change the text directly in the backing store and it isn't in
response to other stuff going on in the NSTextView that causes
synchronous layout and display, and you want your changes visible
immediately, you will have to arrrange for it yourself.
I notice there's also some confusion about the doc. Here are the
classes which play a major role in the new text system and what
framework they reside in. Spec sheets for all these classes should be
there.
NSString/NSMutableString - Foundation
NSAttributedString/NSMutableAttributedString - Foundation (with
extensions in AppKit)
NSTextStorage - AppKit
NSLayoutManager - AppKit
NSTextContainer - AppKit
NSText - AppKit (abstract base class for NSTextView)
NSTextView - AppKit
NSTextAttachment - AppKit
NSTextAttachmentCell - AppKit
Everyone should learn about NSString whether you're going to use the
text system or not. If you're going to use the text system for anything
but the most simplistic situations, you'll want to familiarize yourself
with NSTextView and NSTextStorage (including the API they inherit). You
probably don't need to worry about NSLayoutManager or NSTextContainer or
the NSTextAttachment stuff unless you're doing pretty advanced stuff.
Also, please take a peek at the Text System Overview documentation. It
provides a pretty good introduction to the way the text system works.
Mike Ferris