Не удается заставить UIMenuController отображать пользовательские элементы

Итак, я не уверен, что я делаю что-то не так, но у меня есть UIViewController, на котором есть UICollectionView. В методе viewDidLoad UIViewController я делаю следующее, он не добавляет никаких настраиваемых элементов меню во всплывающее окно, которое появляется.

UIMenuItem *removeItem = [[UIMenuItem alloc] initWithTitle:@"Remove" action:@selector(handleRemoveItem:)];
UIMenuItem *duplicateItem = [[UIMenuItem alloc] initWithTitle:@"Duplicate" action:@selector(handleDuplicateItem:)];

[[UIMenuController sharedMenuController] setMenuItems:@[removeItem, duplicateItem]];

[removeItem release];
[duplicateItem release];

Я установил collectionView:shouldShowMenuForItemAtIndexPath: и collectionView:canPerformAction:forItemAtIndexPath:withSender: так, чтобы они возвращали YES при любых обстоятельствах, но несмотря ни на что, будут отображаться только «Вырезать», «Копировать» и «Вставить».

Я не реализовал это полностью, или я сделал это не так?

P.S. - Я просмотрел в Google столько примеров, сколько смог, и не нашел ничего, что помогло бы.


person Andrew Riebe    schedule 03.04.2013    source источник


Ответы (3)


Ты прав. Невозможно настроить меню, которое появляется при длительном нажатии на ячейку представления таблицы или ячейки представления коллекции.

Я обсуждаю проблему в своей книге:

http://www.apeth.com/iOSBook/ch21.html#_table_view_menus

Как я уже говорил, Копировать, Вырезать и Вставить — единственные варианты, которые у вас есть. Вам придется заставить меню исходить из чего-то другого, если вы хотите его настроить.

EDIT: в версии моей книги для iOS 7 я демонстрирую способ сделать это. Это то же самое для ячеек табличного представления и ячеек представления коллекции, поэтому я начну с решения для ячейки табличного представления. Хитрость заключается в том, что вы должны реализовать метод действия в подклассе ячейки. Например, если ваш настраиваемый селектор действий — abbrev:, вы должны создать подкласс ячейки и реализовать abbrev::

https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/iOS7bookExamples/bk2ch08p454tableCellMenus2/ch21p718sections/MyCell.m

Это единственная сложная часть. Затем, вернувшись в свой класс контроллера, вы делаете для abbrev: в точности то же, что и для любого меню. В shouldShowMenuForRowAtIndexPath: добавьте его в пользовательское меню. Затем реализуйте canPerformAction: и performAction: так, как вы ожидаете (прокрутите до конца):

https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/iOS7bookExamples/bk2ch08p454tableCellMenus2/ch21p718sections/RootViewController.m

Вот параллельная реализация для ячеек представления коллекции: подкласс ячейки:

https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/iOS7bookExamples/bk2ch08p466collectionViewFlowLayout2/ch21p748collectionViewFlowLayout2/Cell.m

И контроллер (листайте до самого низа):

https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/iOS7bookExamples/bk2ch08p466collectionViewFlowLayout2/ch21p748collectionViewFlowLayout2/ViewController.m

Эти подходы также переведены на Swift (не без труда) в версии моей книги для iOS 8.

person matt    schedule 03.04.2013
comment
Да, я как бы почувствовал это, поэтому я изменил то, как я использую его для отображения UIActionSheet на данный момент. Как только у меня появится возможность создать собственное представление коллекции, я, вероятно, реализую это. Спасибо! - person Andrew Riebe; 03.04.2013
comment
Также, пожалуйста, сообщите об ошибке в Apple. Это действительно глупое ограничение. - person matt; 03.04.2013
comment
это работает, если вы делаете это следующим образом, paulsolt.com/2012/ 11/ хорошо это было в ios6 - person DogCoffee; 13.09.2013
comment
Ну, я думаю, вы можете сделать. Вот способ: UIMenuItem *duplicateMenuItem = [[UIMenuItem alloc] initWithTitle:@"duplicate"] action:@selector(duplicate:)]; _menuController.menuItems = [NSArray arrayWithObjects:duplicateMenuItem,nil]; И, конечно же, вы должны определить селектор: - (void)duplicate:(id)sender { // do your stuff; } - person Sourabh Bhardwaj; 18.12.2014
comment
@Sourabh В конце концов я нашел способ сделать это. Я изменю свой ответ, чтобы описать его. - person matt; 18.12.2014

Мне удалось реализовать пользовательские меню в UICollectionViewCell, следуя инструкциям по этой ссылке (https://stackoverflow.com/a/13618212/2313416) с некоторой импровизацией.

В моем UICollectionViewController я реализовал пользовательские элементы меню, добавив их в контроллер меню, как в ссылке.

Затем я реализовал следующее в UICollectionViewController:

- (BOOL)collectionView:(UICollectionView *)cv canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
return NO;
}

- (BOOL)collectionView:(UICollectionView *)cv shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}

- (void)collectionView:(UICollectionView *)cv performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {

NSLog(@"perform action:%@", NSStringFromSelector(action));
}

В моем UICollectionViewCell я реализовал примерно следующее:

- (BOOL)canBecomeFirstResponder {
return YES;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {

if (action == @selector(onCustom1:)) {
    return YES;
}

if (action == @selector(onCustom2:)) {
    return YES;
} 
return NO;
}

Эти действия должны быть такими же, как реализованы в контроллере коллекции.

Если кто-то хочет включить функции копирования или вставки, добавьте их в canPerformAction: и затем измените collectionView::canPerformAction: так, чтобы он возвращал YES.

Это может быть не лучший способ сделать это, но сработал для меня.

person Jan-Michael    schedule 24.04.2013
comment
Это вызывает сбой, так как он не может найти onCustom1: как вы перенаправили его в collectionView? - person Ryan Poolos; 07.05.2013
comment
@RyanPoolos В представлении CollectionViewControllerDidLoad я создал NSArray пользовательских объектов UIMenuItems. Для их действий я поставил '@action(onCustom1:)' и '@action(onCustom2:)'. В заголовочном файле UICollectionViewCell я объявил «-(void)onCustom1:(id)sender» и «-(void)onCustom2:(id)sender». Затем методы были помещены в мой файл UICollectionViewCell.m. - person Jan-Michael; 08.05.2013
comment
Ох, хорошо. Я думал, ты нашел способ каким-то образом связать камеру и коллекцию. - person Ryan Poolos; 08.05.2013
comment
добавление этого в ячейку collectionView работало как шарм. Раньше это работало в ios6 paulsolt.com/2012/11/ но остановился на ios7, поэтому с вашим советом мое приложение снова заработало! - person DogCoffee; 13.09.2013

Шаг 1: Создайте пункты меню

UIMenuItem* miCustom1 = [[UIMenuItem alloc] initWithTitle:@"Custom 1" action:@selector(onCustom1:)];
UIMenuItem* miCustom2 = [[UIMenuItem alloc] initWithTitle: @"Custom 2" action:@selector(onCustom2:)];

Шаг 2: Создайте MenuController

UIMenuController* mc = [UIMenuController sharedMenuController];

Шаг 3: Добавьте элементы в контроллер меню

mc.menuItems = [NSArray arrayWithObjects: miCustom1, miCustom2, nil];

Шаг 4: Создайте методы действий для элементов

- (void) onCustom1: (UIMenuController*) sender
{
}

- (void) onCustom2: (UIMenuController*) sender
{
}

Шаг 5: необязательно установить FirstResponder для действий

- (BOOL) canPerformAction:(SEL)action withSender:(id)sender
{
    if ( action == @selector( onCustom1: ) )
    {
        return YES; // logic here for context menu show/hide
    }

    if ( action == @selector( onCustom2: ) )
    {
        return NO;  // logic here for context menu show/hide
    }

    if ( action == @selector( copy: ) )
    {
        // turn off copy: if you like:
        return NO;
    }

    return [super canPerformAction: action withSender: sender];
}

Шаг 6: Наконец, покажите свой MenuController на некотором действии кнопки

UIMenuController* mc = [UIMenuController sharedMenuController];

CGRect bounds = sender.view.bounds;

[mc setTargetRect: sender.view.frame inView:sender.view.superview];
[mc setMenuVisible:YES animated: YES];
person Dipen Panchasara    schedule 03.04.2013
comment
К сожалению, это не работает в классе UICollectionView. - person Andrew Riebe; 03.04.2013
comment
@AndrewRiebe, вы нашли решение для класса UICollectionView? - person Chintan; 27.08.2015