[Résolu] Utilisation de NSViewController pour code réutilisable.

mybofymybofy Membre
août 2013 modifié dans API AppKit #1

Bonjour.


OXS 10.7.5 - XCode 4.6.3


J'ai une application avec plusieurs fenêtres présentant des parties similaires.


L'idée est de créer chacune de ces parties avec un NSViewController avec IB.


Ainsi, la fenêtre F0 comprend les parties P0 et P1, la fenêtre F1 uniquement la partie P0,


la fenêtre F2 uniquement la partie P1, etc.


La partie P0 comprend un bouton B0 créé par l'IB associé.


Tout marche OK quant à  l'affichage.


Problème : si je clique sur B0, j'ai une erreur lldb.


Donc, je crée une instance Button de NSButton, avec un mouseDown standard.


Dans I'Identity inspector, je choisi Button au lieu de NSButton pour B0.


Tout serait OK si : le mouseDown réagit normalement ... mais B0 ne s'affiche pas !


ça veut dire que je dois chercher B0 à  l'aveuglette.


J'ai beau essayer des tas de choses genre [B0 display], [B0 setBordered:...], ...


impossible d'afficher B0 !


Dans F0 :



ViewController *viewController = [[ViewController alloc] initWithNibName:@ViewController bundle:nil];
...
[[_window contentView] addSubview:[viewController view]];


Merci de l'aide.


Réponses

  • CéroceCéroce Membre, Modérateur
    août 2013 modifié #2

    J'ai un peu de mal à  suivre ton message, et ce que tu as essayé de faire... un peu d'ordre, de code et les messages d'erreur nous aideraient.


     


    Si les boutons ne s'affichent pas, c'est peut-être parce que la vue enfant dépasse de la vue parent. Dans le code d'exemple que tu donnes, il manque au moins un changement de taille de la vue:



    viewController.view.frame = self.window.contentView.bounds;

    Fais également attention au redimensionnement automatique effectué par l'autolayout (ou autoresizing mask, si tu as désactivé l'autolayout).


  • mybofymybofy Membre
    août 2013 modifié #3

    Merci


    Aperçus : http://mybofy.net


    Voici le code :



    ++++++++ Classe AppDelegate : .h
    #import <Cocoa/Cocoa.h>
    #import "ViewController.h"
    @interface AppDelegate : NSObject <NSApplicationDelegate>
    @property (assign) IBOutlet NSWindow *window;
    @property (weak) IBOutlet NSButton *boutonX;
    - (IBAction)boutonX:(id)sender;
    @end .m
    #import "AppDelegate.h"
    @implementation AppDelegate
    @synthesize window=_window;
    @synthesize boutonX=_boutonX;
    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application
    }
    - (IBAction)nouveau:(id)sender {
    ViewController *viewController = [[ViewController alloc] initWithNibName:@ViewController bundle:nil];
    [[_window contentView] addSubview:[viewController view]];
    }
    - (IBAction)boutonX:(id)sender {
    NSLog(@action : boutonX);
    }
    @end
    ++++++++ Classe ViewController : .h
    #import <Cocoa/Cocoa.h>
    #import "Button.h"
    @interface ViewController : NSViewController
    @property (strong) IBOutlet NSView *uneView;
    @property (weak) IBOutlet NSButton *bouton0;
    @property (weak) IBOutlet Button *bouton1;
    - (IBAction)bouton0:(id)sender;
    - (IBAction)bouton1:(id)sender;
    @end .m
    #import "ViewController.h"
    @interface ViewController ()
    @end
    @implementation ViewController
    @synthesize uneView=_uneView;
    @synthesize bouton0=_bouton0;
    @synthesize bouton1=_bouton1;
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    // Initialization code here.
    }
    return self;
    }
    - (IBAction)bouton0:(id)sender {
    NSLog(@action : bouton0);
    }
    - (IBAction)bouton1:(id)sender {
    NSLog(@action : bouton1);
    }
    @end
    ++++++++ Classe Button : .h
    #import <Cocoa/Cocoa.h>
    @interface Button : NSButton
    @end .m
    #import "Button.h"
    @implementation Button
    - (void)mouseDown:(NSEvent *)theEvent {
    NSLog(@mouseDown : Button);
    }
    - (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
    // Initialization code here.
    }
    return self;
    }
    - (void)drawRect:(NSRect)dirtyRect {
    // Drawing code here.
    }
    @end


  • CéroceCéroce Membre, Modérateur
    Normal, si tu surcharges la méthode -drawRect de NSButton, mais que tu ne dessines rien dedans, ben tu vois rien.


  • Normal, si tu surcharges la méthode -drawRect de NSButton, mais que tu ne dessines rien dedans, ben tu vois rien.




     


    Ben oui, c'est évident.


    En plus, je me suis déjà  fait avoir...


     


    Grand merci à  tous.

  • CéroceCéroce Membre, Modérateur

    En règle générale, on n'a pas besoin d'hériter des éléments d'IHM (hormis NSView, pour laquelle on le fait couramment).


    Le design pattern Modèle-Vue-Contrôleur fait que c'est inutile; il suffit d'ajouter des actions aux NSControls comme tu l'as fait plus haut.


  • Bon.


    J'aimerais tout de même comprendre pourquoi un clic sur bouton0 (NSButton) plante systématiquement


    (erreur lldb :


    libobjc.A.dylib`objc_msgSend:


    0x7fff8bcc5e80:  testq  %rdi, %rdi


    0x7fff8bcc5e83:  je     0x7fff8bcc5eb0            ; objc_msgSend + 48


    0x7fff8bcc5e85:  testb  $1, %dil


    0x7fff8bcc5e89:  jne    0x7fff8bcc5ec7            ; objc_msgSend + 71


    etc.)

    Sous-classer NSButton en Button est évidemment un pis aller pas vraiment robuste.

     

    ça paraà®t pourtant simple de créer une vue "maVue" et d'y ajouter des objets (contrôles et autres) avec le ViewController + xib : tout semble fonctionner comme pour AppDelegate + MainMenu.xib basique.

    Ensuite ajouter "maVue" comme sous-vue de la vue de la fenêtre principale paraà®t simple.

    Pourquoi les objets de "maVue" ne se comportent pas alors comme ceux de la vue de la fenêtre principale ?

    Il y a un gros quelque chose qui m'échappe !

  • FKDEVFKDEV Membre
    août 2013 modifié #8
    As-tu quelque chose pour retenir le viewcontroller de ta vue "mavue" ?

    Par exemple un IBOutlet strong dans le controller principale.


    Sinon as-tu essayé d'activer les NSZombie ?
  • Apparemment le IBOutlet strong marche !!!


    Finalement, c'est logique : il faut indiquer qu'un objet va prendre place parmi les objets de la fenêtre.


     


    Encore merci à  tous.

Connectez-vous ou Inscrivez-vous pour répondre.