Как продлить NSTextStorage? - PullRequest
10 голосов
/ 11 мая 2011

Согласно документации, я пытаюсь создать подкласс NSTextStorage и использовать его в текстовом представлении:

/*
 NSTextStorage is a semi-abstract subclass of NSMutableAttributedString. It
 implements change management (beginEditing/endEditing), verification of
 attributes, delegate handling, and layout management notification. The one
 aspect it does not implement is the actual attributed string storage --- this is
 left up to the subclassers, which need to override the two
 NSMutableAttributedString primitives:

 - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str;
 - (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range;

*/

Поэтому я пытаюсь использовать делегат для обработки всех необходимых событий с той же функциональностью:

@implementation MyTextStorage

- (id) init {
    self = [super init];

    if (self != nil) {
        storage = [[NSMutableAttributedString alloc] init];
    }

    return self;
}

- (void) dealloc {
    [storage release];
    [super dealloc];
}

- (NSString *) string {
    return [storage string];
}

- (void) replaceCharactersInRange:(NSRange)range withString:(NSString *)str {
    [storage replaceCharactersInRange:range withString:str];
}

- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range {
    [storage setAttributes:attrs range:range];
}


@end

Неважно, что я использую в качестве делегата: NSTextStorage или NSMutableAttributedString, результат один и тот же:

Возникло необученное исключение * NSRunStorage, _NSBlockNumberForIndex (): индекс (18446744073709551615) за пределами массива границы (0) * Завершение приложения из-за необработанного исключения «NSRangeException», причина: '*** NSRunStorage, _NSBlockNumberForIndex (): индекс (18446744073709551615) за пределами массива границы (0) '

Трассировка стека:

0   CoreFoundation                      0x00007fff840cd7b4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x00007fff885390f3 objc_exception_throw + 45
    2   CoreFoundation                      0x00007fff840cd5d7 +[NSException raise:format:arguments:] + 103
    3   CoreFoundation                      0x00007fff840cd564 +[NSException raise:format:] + 148
    4   AppKit                              0x00007fff86cc6288 _NSBlockNumberForIndex + 86
    5   AppKit                              0x00007fff86cc71d5 -[NSLayoutManager textContainerForGlyphAtIndex:effectiveRange:] + 364
    6   AppKit                              0x00007fff86d1f121 -[NSTextView(NSSharing) didChangeText] + 340
    7   AppKit                              0x00007fff86d44b68 -[NSTextView insertText:replacementRange:] + 2763
    8   CocoaCalculator                     0x0000000100002312 -[CalcTextView insertText:] + 65
    9   CocoaCalculator                     0x00000001000027ac -[CalcTextContainer initWithFrame:] + 1176
    10  AppKit                              0x00007fff86c23d44 -[NSCustomView nibInstantiate] + 646
    11  AppKit                              0x00007fff86b7be17 -[NSIBObjectData instantiateObject:] + 259
    12  AppKit                              0x00007fff86b7b202 -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 336
    13  AppKit                              0x00007fff86b7988d loadNib + 226
    14  AppKit                              0x00007fff86b78d9a +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:]

Завершение начинается, когда я пытаюсь позвонить

[textView insertText:@"123"];

Но в стандартной версии NSTextStorage все работает правильно.

Что мне нужно сделать, чтобы расширить этот класс?

Ответы [ 2 ]

11 голосов
/ 12 мая 2011

В дополнение к примитивным методам NSAttributedString, которые необходимо реализовать, я полагаю, что вам также нужно сделать вызов edited:range:changeInLength: внутри ваших переопределений replaceCharactersInRange:withString: и setAttributes:range: соответственно.

Что-то вроде:

- (void) replaceCharactersInRange:(NSRange)range withString:(NSString *)str {
    [storage replaceCharactersInRange:range withString:str];
    [self edited:NSTextStorageEditedCharacters range:range changeInLength:[str length] - range.length];
}

- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range {
    [storage setAttributes:attrs range:range];
    [self edited:NSTextStorageEditedAttributes range:range changeInLength:0];
}
5 голосов
/ 12 мая 2011

Документация NSTextStorage в этой области немного расплывчата.Комментарий, который вы цитируете в своем вопросе о необходимости переопределить только 2 из NSMutableAttributedString примитивов, означает, что вам не нужно переопределять другие NSMutableAttributedString примитивы.

Вам все равно придется переопределить примитивыдля суперкласса NSAttributedString.Это означает, что вам нужно реализовать -attributesAtIndex:effectiveRange:, -length и -string.Я заметил, что вы включили реализацию -string, поэтому два оставшихся должны это сделать.

Если вы добавите:

- (NSUInteger)length
{
     return [storage length];
}

- (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range
{
      return [storage attributesAtIndex:location effectiveRange:range];
}

... то, надеюсь, это решит эту проблему.

...