#objective-c #macos #voiceover
#objective-c #macos #voiceover
Вопрос:
Я пытаюсь создать пользовательский ротор для выбора одного из нескольких диапазонов в текстовом представлении. API для этого не документирован (хотя и общедоступен), поэтому я адаптировал его из примера кода Apple здесь.
Цель кода — предоставить способ навигации по истории игрового текста, выбрав предыдущую команду или «переместить». Они хранятся как NSArray объектов значений NSRange.
Я получаю список диапазонов, но если я выберу последний, соответствующий диапазон в реальном текстовом представлении не будет выбран. Остальные из них работают так, как задумано. Если я переключусь на другое приложение, а затем обратно, оно внезапно заработает, по крайней мере, до тех пор, пока я не введу другую команду.
Пример кода ниже. Исходный код в контексте здесь. Видео, иллюстрирующее проблему здесь.
- (NSAccessibilityCustomRotorItemResult *)rotor:(NSAccessibilityCustomRotor *)rotor
resultForSearchParameters:(NSAccessibilityCustomRotorSearchParameters *)searchParameters {
NSAccessibilityCustomRotorItemResult *searchResult = nil;
NSAccessibilityCustomRotorItemResult *currentItemResult = searchParameters.currentItem;
NSAccessibilityCustomRotorSearchDirection direction = searchParameters.searchDirection;
NSRange currentRange = currentItemResult.targetRange;
NSUInteger currentItemIndex;
GlkTextBufferWindow *largest = [self largestWithMoves];
if (!largest)
return nil;
NSArray *children = largest.moveRanges;
currentItemIndex = [children indexOfObject:[NSValue valueWithRange:currentRange]];
if (currentItemIndex == NSNotFound) {
// Find the start or end element.
if (direction == NSAccessibilityCustomRotorSearchDirectionNext) {
currentItemIndex = 0;
} else if (direction == NSAccessibilityCustomRotorSearchDirectionPrevious) {
currentItemIndex = children.count - 1;
}
} else {
if (direction == NSAccessibilityCustomRotorSearchDirectionPrevious) {
if ((NSInteger)currentItemIndex == 0) {
currentItemIndex = NSNotFound;
} else {
currentItemIndex--;
}
} else if (direction == NSAccessibilityCustomRotorSearchDirectionNext) {
if (currentItemIndex == children.count - 1) {
currentItemIndex = NSNotFound;
} else {
currentItemIndex ;
}
}
}
if (currentItemIndex == NSNotFound) {
return nil;
}
NSValue *targetRangeValue = children[(NSUInteger)currentItemIndex];
if (targetRangeValue) {
NSRange textRange = targetRangeValue.rangeValue;
searchResult = [[NSAccessibilityCustomRotorItemResult alloc] initWithTargetElement: largest.textview];
searchResult.targetRange = textRange;
// By adding a custom label, all ranges are reliably listed in the rotor
NSString *label = [largest.textview.string substringWithRange:textRange];
searchResult.customLabel = label;
}
return searchResu<
}
Комментарии:
1. Совет: Если документация отсутствует, проверьте заголовки.
2. Спасибо! Это хороший совет, но теперь я понимаю, что упоминание о том, что API недокументирован, неуместно, во-первых, потому что Apple, похоже, в значительной степени отказалась от документирования своих новых API, и все это уже знают, а во-вторых, поработав над этим кодом пару месяцев, ячувствую, что у меня есть разумное представление о том, как работает этот API. Однако это не помогает мне с этой ошибкой.
Ответ №1:
Я предполагаю, что вы передаете текстовый диапазон, который выходит за рамки. Например, вот что я вижу, когда использую меню истории команд. Обратите внимание на «x Closed.», что неверно. Это должно быть «закрыть почтовый ящик закрыт».
Это тоже происходит не всегда. В некоторых (большинстве?) Случаях я могу выбрать последнюю команду из ротора. Поэтому я бы внимательно посмотрел на диапазоны и сравнил те, которые работают, с теми, которые не работают.
Обратите внимание также на дублированную начальную команду на изображении ниже вместо команды «подойти к входной двери». Итак, в текущей реализации есть несколько различных ошибок, которые могут повлиять на поведение, которое вы видите.
Спасибо, что нашли время для поддержки VoiceOver! Это идеальный проект для этого.
Комментарии:
1. Спасибо, что взглянули на это. Похоже, что это проблема типа NSTextView, которая обычно решается путем введения задержки где-нибудь, чтобы дать ему время закончить выкладку текста в каком-то фоновом системном потоке, хотя я не уверен, насколько хорошо это работает с API rotor.
2. Если вы знаете шаги по воспроизведению этой ошибки, пожалуйста, дайте мне знать. Здесь или в репозитории Github проблемы .