NSTextStorage/NSLayoutManager: "Access invalid attribute location 22550 (length 5319) "
NSTextStorage/NSLayoutManager: "Access invalid attribute location 22550 (length 5319) "
- Subject: NSTextStorage/NSLayoutManager: "Access invalid attribute location 22550 (length 5319) "
- From: Jonathan Jackel <email@hidden>
- Date: Mon, 13 Dec 2004 23:25:36 -0500
I am creating a specialized text editor that allows the user to collapse the text down to an outline representation. When the user wants to switch to an outline view, the model object creates an outline version of the main text storage, truncating lines and and adding a triangular text attachment at the beginning of each paragraph. To switch back to the full text, the user simply clicks on the attachment's cell. Programmatically, I tell the text view's layout manager to replaceTextStorage: with the outline version, and then replaceTextStorage: again to go back to the full text.
This all works pretty well, but I want to visually create a "now you see it, now you don't" illusion by making sure that the selected paragraph remains in the same relative position on screen. This works quite excellently (if I do say so myself) when going from outline to full text. It does not work completely in the other direction.
It appears that when I replace the full text NSTextStorage with the shorter, outline version, someone in the Cocoa frameworks is not getting the message that a new, shorter text storage is in the text system hierarchy. When I try to tell the text view to make a valid selection, I get a message like this.
2004-12-13 11:31:22.448 LG[27631] *** Assertion failure in -[NSMutableRLEArray objectAtIndex:effectiveRange:], String.subproj/NSAttributedString.m:1009
2004-12-13 11:31:22.451 LG[27631] Access invalid attribute location 22550 (length 5319)
I've tried various strategies for trying to trigger some sort of clean up on the text storage, including various fixAttributes... methods (in NSTextStorage) and glyphAtIndex... methods (in NSLayoutManager), figuring that all the objects in the hierarchy would somehow figure out that the text storage is now a much shorter string. No luck.
My code appears below. Any help would be appreciated.
Jonathan
In MyDocument.m:
- (id)sender
{
NSRange selection;
unsigned paranumber;
//converter is a model object of class LGConverter
if(![converter isUsingOutlineRep])
{
//Switch to outline rep. Figure out which paragraph the selection is in. paragraphNumberForRange: is defined in a category on NSString
paranumber = [[[converter storage] string] paragraphNumberForRange:[afterTextView selectedRange]];
[converter setOutlineRepresentation:nil]; //this code is below
[[afterTextView layoutManager] replaceTextStorage:[converter outlineRepresentation]];
[converter setIsUsingOutlineRep:YES];
selection = [[[converter outlineRepresentation] string] rangeForParagraphNumber:paranumber]; //I've also tried [[afterTextView textStorage] string]. rangeForParagraphNumber: is defined in a category on NSString
NSLog(@"The selection is at location %d\nLength is %d", selection.location, [[converter outlineRepresentation] length]); // Always a location < length in all testing
[window makeFirstResponder:nil];
[window makeFirstResponder:afterTextView];
[afterTextView setSelectedRange:selection]; //Error seems to occur here.
[afterTextView scrollRangeToVisible:selection];
[sender setState:NSOnState];
} else {
//go back to regular view. This works great.
paranumber = [[[converter outlineRepresentation] string] paragraphNumberForRange:[afterTextView selectedRange]];
[[afterTextView layoutManager] replaceTextStorage:[converter storage]];
[converter setIsUsingOutlineRep:NO];
selection = [[[converter storage] string] rangeForParagraphNumber:paranumber];
[window makeFirstResponder:nil];
[window makeFirstResponder:afterTextView];
[afterTextView setSelectedRange:selection];
[afterTextView scrollRangeToVisible:selection];
[sender setState:NSOffState];
}
}
In LGConverter.m
- (void)setOutlineRepresentation:(NSTextStorage *)newOutlineRepresentation
{
int maxParagraphLength = 100;
newOutlineRepresentation = [[NSTextStorage alloc] initWithAttributedString:[self storage]];
NSArray *paragraphs = [newOutlineRepresentation paragraphs];
NSEnumerator *eParagraphs = [paragraphs objectEnumerator];
NSTextStorage *aParagraph;
NSAttributedString *attachment = [NSAttributedString attributedStringWithAttachment:[[self class] outlineAttachment]];
NSString *empty = @" ";
while(aParagraph = [eParagraphs nextObject])
{
NSDictionary *attributes = [aParagraph attributesAtIndex:0 effectiveRange:nil];
NSMutableAttributedString *lede = [[NSMutableAttributedString alloc] initWithString:empty attributes:attributes];
[lede appendAttributedString:attachment];
[aParagraph insertAttributedString:lede atIndex:0];
if([aParagraph length] > maxParagraphLength)
{
aParagraph = [aParagraph replaceCharactersInRange:NSMakeRange(maxParagraphLength, [aParagraph length] - maxParagraphLength)
withString:@"...\n"];
}
}
[outlineRepresentation release];
outlineRepresentation = newOutlineRepresentation;
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden