После некоторой переделки я думаю, что понял это.Джош, я воспользовался твоим предложением, чтобы начать.Я не уверен, что вы отредактировали свое предложение или просто удалили его, но оно пропало, поэтому я не могу процитировать его в своем ответе.
В любом случае, вы должны сдвигать диапазоны, которые собираетесь заменить после каждоговызов replaceCharactersInRange:withString:
, иначе произойдет что-то плохое, поскольку диапазоны не совпадают.Вот что я закончил:
// array of NSValue objects storing an NSRange
NSArray *replaceRanges = [self replaceRanges];
NSString *replaceString = [self replaceString];
// array of NSString objects you are going to use for the replace operation, just replaceString repeated [replaceRanges count] times
NSArray *replaceStrings = [self replaceStrings];
NSTextView *textView = [self textView];
// the amount we have to shift subequent replace ranges after each call to replaceCharactersInRange:withString:
NSInteger locationShift = 0;
// check to makes sure the replace can occur
if ([textView shouldChangeTextInRanges:replaceRanges replacementStrings:replaceStrings]) {
// we want to treat all these replacements as a single replacement for undo purposes
[[textView textStorage] beginEditing];
for (NSValue *rangeValue in replaceRanges) {
NSRange range = [rangeValue rangeValue];
// replace the range shifted by locationShift with our replaceString
[[textView textStorage] replaceCharactersInRange:NSMakeRange(range.location + locationShift, range.length) withString:replaceString];
// update the shift amount, which is the difference between our replaced string length and the original match length
locationShift += [replaceString length] - range.length;
}
// end the grouping operation
[[textView textStorage] endEditing];
}
Это прекрасно работает и поддерживает отмену, как и ожидалось, отмена этой операции приводит к отмене всех замен сразу.
В любом случае, благодаря Джошу,поскольку его ответ заставил меня указать правильное направление.