Добавление речи в пользовательский UIMenuController

Я создал кастом UIMenuController в UIWebView но, кажется, избавиться от опции "Speak Selection" в UIMenuController после этого. Параметр "Разговор" включен в "Предпочтениях" на всех тестовых устройствах и отображается в других приложениях, включая приложения сторонних производителей. Есть ли служба доступности или часть sharedMenuController что я могу позвонить, чтобы получить этот предмет?

UIMenuItem *copyMenuItem = [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"Copy", @"Copy menu item") action:@selector(myappCopy:)];

UIMenuItem *highlightMenuItem = [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"Highlight", @"Highlight menu option") action:@selector(myappHighlight:)];

UIMenuItem *unhighlightMenuItem = [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"Remove Highlight", @"Remove Highlight menu option")
                                                           action:@selector(myappRemoveHighlight:)];

UIMenuItem *noteMenuItem = [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"Note", @"Note menu options") action:@selector(myappNote:)];

[UIMenuController sharedMenuController].menuItems = [NSArray arrayWithObjects:copyMenuItem, highlightMenuItem, unhighlightMenuItem, noteMenuItem, nil];

[copyMenuItem release];
[highlightMenuItem release];
[unhighlightMenuItem release];
[noteMenuItem release];

Я даже пытался проанализировать существующие общие пункты меню в начале, но я не вижу ничего, что сбрасывается в журнал. Метод вызывается при запуске приложения.

Попробовал это в верхней части метода:

    for (UIMenuItem *menuItem in [UIMenuController sharedMenuController].menuItems) {
        NSLog(@"title: %@", menuItem.title);
        NSLog(@"action: %@", menuItem.action);
    }

Любая помощь высоко ценится! Спасибо - Эрик

2 ответа

Решение

Некоторые из элементов UIMenuController можно найти в UIResponder.h в UIKit Framework.

@interface NSObject(UIResponderStandardEditActions)   // these methods are not implemented     in NSObject

 - (void)cut:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
 - (void)copy:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
 - (void)paste:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
 - (void)select:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
 - (void)selectAll:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
 - (void)delete:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_2);
 - (void)makeTextWritingDirectionLeftToRight:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0);
 - (void)makeTextWritingDirectionRightToLeft:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0);

 @end

Но там нет опции разговорного текста. Оказывается, если вы переопределите "canPerformAction: WithSelector:", в подклассе вашего UIWebView или UITextField, как указано ниже, вы также получите список всех действий, отправленных самому себе, включая параметры UIMenuController.

// Override
- (BOOL) canPerformAction:(SEL)action withSender:(id)sender
{
    NSLog(@"%@",NSStringFromSelector(action));

    //if you are customizing your menu, return NO except for your specific selectors
    return YES;
}

Вы найдете несколько способов, которые могут вас заинтересовать, включая _accessibilitySpeak: и _accessibilityPauseSpeaking: и _define: (обратите внимание, что эти три селектора только для iOS 5). Подчеркивание означает, что они являются частными, поэтому имейте в виду, что вы не можете напрямую вызывать их с помощью классического синтаксиса [селектор классов].

Помните, что это системные элементы меню, что означает, что Apple будет размещать их перед любыми элементами меню, которые вы добавляете, часто оставляя доступ к элементам меню во втором слое, нажав стрелку>. Если вы хотите контролировать порядок отображения элементов и / или смешивать системные элементы Apple с вашими элементами, вам потребуется создать пользовательские элементы меню для этих действий, которые вызывают метод в вашем классе, например:

- (void) myAppSpeak: (UIMenuController*) sender
{
    [super performSelector:@selector(_accessibilitySpeak:)];
}

Имейте в виду, что эти методы должны быть реализованы в подклассе класса, который их уже реализует, например, в подклассе UIWebView.... не в подклассе UIWebViewController.

Затем внутри контроллера или там, где вы строите свой UIMenuController, создайте пользовательскую кнопку, которая вызывает этот метод. Убедитесь, что если вы находитесь в веб-представлении, вы ссылаетесь на объект типа вашего подкласса, а не на общее веб-представление. Иначе это не сработает.

    UIMenuItem *speakMenuItem = [[UIMenuItem alloc] initWithTitle:@"Speak" action:@selector(myAppSpeak:)];

    [UIMenuController sharedMenuController].menuItems = [NSArray arrayWithObjects:speakMenuItem, etc. etc., nil];

Даже если вы добавляете его в пункты вашего меню, оно не появится, если вы не вернете YES для селектора в вашем canPerformAction: WithSelector: в вашем подклассе веб-представления или текстового поля. Так что не стесняйтесь добавлять элементы здесь, которые могут быть косвенными в противном случае. Вы можете использовать логику в своем подклассе, чтобы разобраться в этом.

Я нашел несколько интересных вещей с этой ошибкой. В основном, когда голосовой выбор включен, после того, как вы сделаете первый выбор, UIMenuController освобождается от menuItems, Решение, хотя и хакерское, простое.

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
NSString *selectorString = NSStringFromSelector(action);
BOOL isAccessibilitySelector = [selectorString isEqualToString:@"_accessibilitySpeak:"] || [selectorString isEqualToString:@"_accessibilityPauseSpeaking:"];
if (isAccessibilitySelector && [super canPerformAction:action withSender:sender]) {
    //(re)add menuItems to UIMenuController
    return YES;
}
return NO;

}

Я должен отметить, что вы должны повторно добавить menuItems после их canPerformAction...() был вызван.

Я представил это как радар:12931434. Обновление: DUP'ed до 13060693.

Другие вопросы по тегам