Hello,
I’m attempting to add temporary attributes (all of which do not require layout)
to text as soon as it has been edited if it has a custom attribute applied
(much how the text system automatically applies linkTextAttributes to any text
with an NSLinkAttributeName attribute - although from my various tests and
NSLogging it seems that the text system does that under the hood using some
internal magic and doesn’t use temporary attributes). In another thread on a
related issue Aki Inoue was kind enough to point out that I could override
NSLayoutManager’s -showPackedGlyphs:etc... to change the colour of the text,
but that doesn’t handle underlines or strikethroughs, for which I still need to
apply temporary attributes.
My current solution is to try to override my custom text storage’s
-processEditing method to iterate through the layout managers and apply any
necessary temporary attributes there, something like this:
- (void)processEditing
{
[super processEditing];
NSRange dirtyRange = [self editedRange];
if (dirtyRange.length == 0)
return;
NSEnumerator *e = [[self layoutManagers] objectEnumerator];
NSLayoutManager *lm;
while (lm = [e nextObject])
{
if (dirtyRangeHasMyCustomAttribute)
[lm addTemporaryAttributes:tempAttribs
forCharacterRange:dirtyRange];
}
}
However, the above has massive problems. In certain circumstances it causes
this crash:
-[KBLayoutManager
_fillGlyphHoleForCharacterRange:startGlyphIndex:desiredNumberOfCharacters:] ***
attempted glyph generation while textStorage is editing. It is not valid to
cause the layoutManager to do glyph generation while the textStorage is editing
(ie the textStorage has been sent a beginEditing message without a matching
endEditing.)
I’m not entirely sure why, as I’ve NSLogged all of the beginEditing and
endEditing messages and this code is only ever call after the last -endEditing,
so beginEditing and endEditing should are matching (I even tested it out by
putting it into -endEditing and processing things only after calling [super
endEditing] but had the same crash).
I can avoid the crash by putting the temporary attribute application code into
a separate method and calling it after a zero delay like this:
- (void)processEditing
{
[super processEditing];
[self performSelector:@selector(applyTempAttributesIfNecessaryToRange:)
withObject:[NSValue valueWithRange:[self editedRange] afterDelay:0];
}
But this seems fragile to me. I’m not entirely sure why calling the same code
after a delay of 0 would prevent the crash, or confident that it will work in
all situations.
Has anyone tried to do something similar and found a better solution to what
I’m trying to do?
Many thanks in advance and all the best,
Keith
_______________________________________________
Cocoa-dev mailing list ([email protected])
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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]