Accéder au contenu principal

UIMenuBuilder avec MacCatalyst

Lorsque l'on porte une application IOS sur MacCatalyst, se pose la question du menu.
Ici je voulais ajouter un menu "Open" à mon application, mais comment faire ?

J'ai mis mon code entre "#if TARGET_OS_MACCATALYST" car ce code fonctionne aussi avec IOS el la notion de UIMenuBuilder n'apparait que dans IOS13, or je développe mes application pour IOS9 car beaucoup d'utilisateurs ont des vieux appareils...

#if TARGET_OS_MACCATALYST

-(void)buildMenuWithBuilder:(id)builder {

    NSLog(@"buildMenuWithBuilder !!");
    [super buildMenuWithBuilder:builder];

    if(builder.system == UIMenuSystem.mainSystem) {

        [builder removeMenuForIdentifier:UIMenuFormat]; 
        // Le menu "Format" ne m'interresse pas

        // On crée la commande... 
        //L'action doit être une fonction déclarée dans le FirstResponder
        UIKeyCommand *command_O = [UIKeyCommand 
                 commandWithTitle:@"Import"
                            image:nil                                                       
                           action:NSSelectorFromString(@"importfile:")
                            input:@"O"
                    modifierFlags:UIKeyModifierCommand
                     propertyList:nil];

        // On crée l'entrée du menu à partir de la commande
        UIMenu *menu = [UIMenu 
                    menuWithTitle:@""              // Inutilisé ici
                            image:nil              // Utile que sous IOS
                       identifier:@"UTI unique"    // Un nom unique
                          options:UIMenuOptionsDisplayInline
                         children:@[ command_O ]]; // Une seule commande

        // On insert l'entrée de menu 
        // en première position dans le menu Fichier.
        [builder insertChildMenu:menu atStartOfMenuForIdentifier:UIMenuFile];

    }
}


#endif

Donc la fonction buildMenuWithBuilder: doit être ajouté dans le AppDelegate.m et contenir :
- L'appel à [super BuildMenuWithBuilder:builder]; pour que l'app crée bien le menu.
- Un test pour vérifier que l'on parle bien du menu système, et si ce n'est pas le cas ne rien faire.
- Vous pouvez supprimer des menu que vous ne voulez pas avec [builder removeMenuForIdentifier:], les menus standards ont évidemment leur constante de définit (comme ici UIMenuFormat).
- Pour chaque entrée du menu :
  - On crée le UIKeyCommand qui définit quelle action va être effectuée.
  - On crée le UIMenu avec UIMenuOptionDisplayInline pour une entrée simple (pas de sous menu).
  - On insère le menu au début ou à la fin d'un menu déjà présent.

Voilà, le menu "Open" apparait... Mais petite remarque sur l'action de la UIKeyCommand. Vous aurez peut-être remarqué qu'il n'y a pas de Target et que j'ai utilisé NSSelectorFromString() ) la place de @selector().

En fait l'action doit être faite par le FirstResponder. C'est pourquoi on ne peut pas utilise @selector() qui est une macro du précompilateur. La fonction pointée par action n'existe pas ici dans le AppDelegate, je l'ai mise dans la classe de mon premier ViewController.  Il faut donc utiliser NSSelectorFromString() pour éviter un Warning, car la fonction n'est pas visible par le compilateur.

Ce système est très intéressant car si la fonction n'est pas définie dans le FirstResponder, l'entrée dans le menu est grisée automatiquement. 

Donc cas 1 : 

Imaginons que vous ayez un premier ViewController qui répond à l'action open, le menu apparait actif, même si l'on passe dans un autre ViewController, l'action reste active car le FirstResponder est capable de répondre à tous les sélecteurs définis dans sa classe, mais aussi à tous les sélecteurs définis dans le ViewController parents.

Et cas 2 :

Si nous définissons notre action dans un ViewController qui n'est pas le root, ce n'est que quand notre ViewController sera actif que l'entrée de menu sera active, et elle restera active même si le ViewController présente de nouveaux ViewController. Et évidemment elle redeviendra inactive si l'on quitte le ViewController.




Commentaires

Posts les plus consultés de ce blog

Tailles d'écran et iTunesConnect

 Lorsque l'on crée une nouvelle application, nous devons inclure des photos d'écran dans l'interface d'iTunes Connect :      Pour l'iPad, ce n'est pas bien compliqué, c'est indiqué, : Il faut les photos d'écran d'un iPadPro 12,9 pouce de 6ème (sans bouton home) et de 2e génération (avec le bouton home). Mais pour les iPhone c'est plus problématique, car il n'est indiqué que la taille de l'écran, et pas le modèle de l'appareil. Or dans la sélection des simulateurs, il n'y a pas les tailles des écrans des différent modèles ! Il faut donc se renseigner ici ;-) Appareil Taille iTunes Connect iPhone Pro Max 12, 13 6,7” Optionnel iPhone 11 Pro Max 6,5” Obligatoire iPhone 11, 12, 13 iPhone Pro 12, 13 6,1” iPhone X 5,8” iPhone 6+, 6S+, 7+, 8+ 5,5” Obligatoire iPhone 6, 6S, 7, 8 4,7” iPhone 5, 5S, SE 4” iPhone 4s 3,5” Personnellement, je ne savais pas que l'iPhone 11 Pro Max était le seul iPhone avec un écran 6,5 pouces !

Les bases de la programmation : Le binaire

Le binaire ”Ce monde est un code binaire où nous avons seulement deux options : accepter ou refuser. ” Ardit BEQIRI Lorsque l’on parle d’ordinateur on dit très souvent que ce n’est qu’un outil qui traite des 0 et 1, et ce n’est pas faux. Si l’on résume un ordinateur à de l’électronique, effectivement la mémoire, le processeur, les périphériques peuvent se résumer à des suites binaires, donc des suites de 0 et de 1. Mais c’est comme dire que le cerveau n’est qu’un imbroglio de neurones, c’est réducteur. La complexité du système est tel que l’on peut oublier qu’à la base c’est un système binaire, du reste un utilisateur d’ordinateur n’a même pas à savoir comment cela fonctionne, et même un programmeur n’a pas toujours à le savoir. Cependant, tous les langages informatiques comprennent une partie binaire. Et donc la compréhension du binaire est essentielle à un moment ou à un autre. En fait il y a plusieurs sujets interconnectés, la logique binaire, les opérations binaires, les nombr

xCode: auto-incrémentation du BUILD_VERSION

 Lorsque vous envoyez votre application à Apple, vous devez mettre à jour deux valeurs, le numéro de version et le numéro de build : Pour le numéro de Version, ce n'est pas vraiment un problème puisque celui-ci n'augmente que lors d'une mise à jour sur l'appStore. Cela peut être fait à la main. Pour le numéro de Build, c'est plus embêtant. Si vous êtes comme moi, et que vous faites de nombreuses bêta, il faut mettre à jour le numéro à chaque envoi de l'app, et on oublie souvent d'incrémenter la valeur. Le plus simple est alors d'incrémenter automatiquement la valeur à chaque compilation. Ainsi plus besoin de s'en occuper. J'avais trouvé ce script, à insérer avant la compilation : Cela fonctionnait très bien, mais xCode a changé, et les nouveaux projets ne range plus directement le numéro de Build dans le fichier Info.plist et cela ne fonctionne donc plus. J'ai donc cherché une nouvelle méthode, et la voici. Tout d'abord il faut changer l&