NSLinguisticTagger关于NSTextStorage崩溃错误的内容

时间:2014-06-04 14:18:52

标签: objective-c xcode nstextstorage

我正在尝试使用NSLinguisticTagger来监控NSTextStorage的内容,并根据用户输入的内容提供一些上下文信息。为此,我有一个OverlayManager对象,它将这种关系连接起来:

-(void) setView:(NSTextView*) view {
    _view = view;
    _layout = view.layoutManager;
    _storage = view.layoutManager.textStorage; //get the TextStorage from the view
    [_tagger setString:_storage.string]; //pull the string out, this grabs the mutable version
    [self registerForNotificationsOn:self->_storage]; //subscribe to the willProcessEditing notification
}

当编辑发生时,我确保将其捕获并通知标记器(是的,我知道我与成员访问权限令人讨厌,我在Obj-C上生锈了,我稍后会修复它) :

- (void) textStorageWillProcessEditing:(NSNotification*) notification{
    if ([self->_storage editedMask] & NSTextStorageEditedCharacters) {
        NSRange editedRange = [self->_storage editedRange];
        NSUInteger delta = [self->_storage changeInLength];
        [_tagger stringEditedInRange:editedRange changeInLength:delta]; //should notify the tagger of the changes- if I replace this line with [_tagger setString:[_storage string]] it works, but gobbles CPU as it retags the entire string
        [self highlightEdits:self];
    }
}

highlightEdits消息将作业委托给“Overlay”对象池。每个代码都包含一个与此类似的代码块:

[tagger enumerateTagsInRange:range scheme:NSLinguisticTagSchemeLexicalClass options:0 usingBlock:^(NSString *tag, NSRange tokenRange, NSRange sentenceRange, BOOL *stop) {
            if (tag == PartOfSpeech) {
                [self applyHighlightToRange:tokenRange onStorage:storage];
            }
        }];

这就是问题所在 - enumerateTagsInRange方法崩溃了一条消息:

2014-06-04 10:07:19.692 WritersEditor[40191:303] NSMutableRLEArray     replaceObjectsInRange:withObject:length:: Out of bounds

如果我没有链接到底层字符串的可变副本而是执行[[_storage string] copy],那么不会发生 ,但显然我不想复制每次我想做标记时,整个后备存储。这一切都应该在主运行循环中发生,所以我不认为这是一个线程问题。我正在枚举标签的NSRange存在于NSLinguisticTagger的字符串视图中的NSTextStorage 中。这甚至不是applyHighlightToRange调用向字符串添加属性的事实,因为它甚至在到达该行之前崩溃。

我试图针对这个问题构建一个测试用例,但在这些情况下无法复制它:

- (void) testEdit
{
    NSAttributedString* str = [[NSMutableAttributedString alloc] initWithString:@"Quickly, this is a test."];
    text = [[NSTextStorage alloc] initWithAttributedString:str];

    NSArray* schemes = [NSLinguisticTagger availableTagSchemesForLanguage:@"en"];
    tagger = [[NSLinguisticTagger alloc] initWithTagSchemes:schemes options:0];
    [tagger setString:[text string]];

    [text beginEditing];
    [[text mutableString] appendString:@"T"];
    NSRange edited = [text editedRange];
    NSUInteger length = [text changeInLength];
    [text endEditing];

    [tagger stringEditedInRange:edited changeInLength:length];
    [tagger enumerateTagsInRange:edited scheme:NSLinguisticTagSchemeLexicalClass options:0 usingBlock:^(NSString *tag, NSRange tokenRange, NSRange sentenceRange, BOOL *stop) {
        //doesn't matter, this should crash
    }];
}

该代码不会崩溃。

0 个答案:

没有答案