web-dev-qa-db-fra.com

Comment pouvez-vous VRAIMENT enlever Copy from UIMenuController

Il existait apparemment un moyen facile d'empêcher que le libellé "Plus ..." n'apparaisse dans UIMenuController lorsque vous avez ajouté plusieurs éléments de menu personnalisés. Il vous suffisait de supprimer tous les éléments du menu système. Il y avait même une solution de contournement ici pour avoir encore du travail de copie. Il vous suffisait d'implémenter une commande de copie personnalisée à l'aide d'un sélecteur différent, puis de remplacer canPerformAction: withSender: pour ne pas afficher la copie système:

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender 
{
    if (action == @selector(copy:))
       return NO;
    else
       // logic to show or hide other things
}

Malheureusement, cette méthode ne fonctionne plus (au moins dans une sous-classe UIWebView). canPerformAction: withSender: est appelé pour chaque élément du menu système à l'exception de la commande copy: le résultat est que l'élément de menu de la copie système est toujours affiché. Cela signifie que si vous avez plusieurs éléments de menu personnalisés, ils sont toujours cachés derrière "Plus ...".

Alors, existe-t-il un moyen de vraiment supprimer l'élément de copie du système ou un autre moyen d'empêcher les éléments de menu de se cacher derrière "Plus ..."?

Mise à jour

Voici le résultat obtenu lorsque je remplace canPerformAction: withSender: vous remarquerez que la méthode n'est jamais appelée pour l'action "copy:":

cannot perform action cut: with sender <UIMenuController: 0x7227d30>.
cannot perform action select: with sender <UIMenuController: 0x7227d30>.
cannot perform action selectAll: with sender <UIMenuController: 0x7227d30>.
cannot perform action paste: with sender <UIMenuController: 0x7227d30>.
cannot perform action delete: with sender <UIMenuController: 0x7227d30>.
cannot perform action promptForReplace: with sender <UIMenuController: 0x7227d30>.
cannot perform action _showMoreItems: with sender <UIMenuController: 0x7227d30>.
cannot perform action _setRtoLTextDirection: with sender <UIMenuController: 0x7227d30>.
cannot perform action _setLtoRTextDirection: with sender <UIMenuController: 0x7227d30>.
can perform action customCopy: with sender <UIMenuController: 0x7227d30>.
can perform action custom1: with sender <UIMenuController: 0x7227d30>.
cannot perform action custom2: with sender <UIMenuController: 0x7227d30>.
can perform action custom3: with sender <UIMenuController: 0x7227d30>.
can perform action custom4: with sender <UIMenuController: 0x7227d30>.
cannot perform action cut: with sender <UIMenuController: 0x7227d30>.
cannot perform action select: with sender <UIMenuController: 0x7227d30>.
cannot perform action selectAll: with sender <UIMenuController: 0x7227d30>.
cannot perform action paste: with sender <UIMenuController: 0x7227d30>.
cannot perform action delete: with sender <UIMenuController: 0x7227d30>.
cannot perform action promptForReplace: with sender <UIMenuController: 0x7227d30>.
cannot perform action _showMoreItems: with sender <UIMenuController: 0x7227d30>.
cannot perform action _setRtoLTextDirection: with sender <UIMenuController: 0x7227d30>.
cannot perform action _setLtoRTextDirection: with sender <UIMenuController: 0x7227d30>.
21
lfalin

La technique que vous avez liée semble toujours fonctionner. J'ai implémenté une sous-classe UIWebView avec ces méthodes et seuls les éléments A et B sont apparus.

+ (void)initialize
{
    UIMenuItem *itemA = [[UIMenuItem alloc] initWithTitle:@"A" action:@selector(a:)];
    UIMenuItem *itemB = [[UIMenuItem alloc] initWithTitle:@"B" action:@selector(b:)];
    [[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObjects:itemA, itemB, nil]];
    [itemA release];
    [itemB release];
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    BOOL can = [super canPerformAction:action withSender:sender];
    if (action == @selector(a:) || action == @selector(b:))
    {
        can = YES;
    }
    if (action == @selector(copy:))
    {
        can = NO;
    }
    NSLog(@"%@ perform action %@ with sender %@.", can ? @"can" : @"cannot", NSStringFromSelector(action), sender);
    return can;
}
13
lemnar

pour ios> = 5.1 canPerformAction: (SEL) action avecSender: l'expéditeur (id) ne fonctionne plus.

Si vous êtes d'accord avec simplement désactiver l'action coller, voici une méthode:

ajouter UITextFieldDelegate à votre contrôleur de visualisation et à la méthode d'implémentation de ce type

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
if(textField == txtEmailRe)
    return ((string.length) > 1 ? NO : YES);
}

cela signifie que si l'utilisateur entre plus d'un caractère pour chaque action (cela signifie probablement que l'utilisateur est en train de coller quelque chose), ne l'acceptez pas dans le champ de texte.

c'est une bonne pratique pour forcer l'utilisateur à entrer des champs de texte comme le courrier électronique et

7
Canberk Ersoy

Voici une solution pour iOS5.x qui fonctionne pour moi. C'est par Josh Garnham, suggérant de créer une catégorie UIWebBrowserView pour attraper la copie :, coller :, définir: les sélecteurs.

http://ios-blog.co.uk/iphone-development-tutorials/rich-text-editing-highlighting-and-uimenucontroller-part-3/

@implementation UIWebBrowserView (UIWebBrowserView_Additions)
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    return NO;
}
@end

Remarquez simplement FTR: Il y a une légère faute de frappe sur cette excellente page Web. Voici précisément comment vous le faites. Apple va 100% rejettera cela. Créer une catégorie

enter image description here

(Vous devez taper "UIWebBrowserView" car Xcode n'ouvrira pas les classes privées.) Texte intégral des fichiers .h et .m:

// .h file...
#import "UIWebBrowserView+Tricky.h"
@interface UIWebBrowserView : UIView
@end
@interface UIWebBrowserView(Tricky)
@end

// .m file...
#import "UIWebBrowserView+Tricky.h"
@implementation UIWebBrowserView (Tricky)
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
NSLog(@"don't let Apple see this");
return NO;
}
@end

Pour la petite histoire, un "simple clic" fera quand même apparaître les suggestions ennuyeuses de vérificateur orthographique! Mais sinon, le menu contextuel du double-clic est totalement supprimé, il est rejeté à 100% par Apple.

3
auco

la réponse de Lemnar est correcte. L'implémentation d'une sous-classe de UIWebView fonctionne parfaitement. Cet exemple convient pour une UITextView. Pour UIWebView, créez une sous-classe personnalisée comme suit:

//
//  MyUIWebView.h
//

#import <UIKit/UIKit.h>

@interface MyUIWebView : UIWebView

@end

Et:

//
//  MyUIWebView.m
//

#import "MyUIWebView.h"

@implementation MyUIWebView

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender 
{
    if (action == @selector(copy:))
        return NO;
    else
        // logic to show or hide other things
}

@end

Ensuite, au lieu d'instancier UIWebView, utilisez MyUIWebView.

UPDATE:

Si vous souhaitez désactiver "copier" mais laisser "définir" (et "traduire",) ce qui peut être utile, voici comment procéder; remplacez canPerformAction:withSender ci-dessus par ceci:

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender 
{
    if (action == @selector(defineSelection:))
    {
        return YES;
    }
    else if (action == @selector(translateSelection:))
    {
        return YES; 
    }
    else if (action == @selector(copy:))
    {
        return NO;
    }

    return [super canPerformAction:action withSender:sender];
}
3
Adriano Lucas

Je suis désolé pour mon anglais. Mais il y a une idée.

Je pense que la méthode canPerformAction a été appelée plusieurs fois, mais vous ne la manipulez qu'une fois. Dans ce cas, je pense qu'il peut y avoir un autre contrôle d'interface utilisateur a appelé. Par exemple, le contrôle UITextView dans votre UIWebView.

Je suppose que vous pouvez générer l'interface utilisateur par storyboard. Tous les contrôles du storyboard n'ont pas leur propre classe. Vous pouvez définir une classe pour le contrôle de réponse et réécrire sa méthode canPerformAction.

1
sandycs

Vous pouvez dessiner votre propre menu au lieu d'utiliser UIMenuController. De cette façon, vous pouvez afficher autant d'éléments que vous le souhaitez en même temps sans utiliser Autre.

0
LaC