NSDocument et Multi NIB

soraya_sochsoraya_soch Membre
08:38 modifié dans API AppKit #1
Bonjour à  tous,

J'ai une application qui ne contient qu'1 NIB, et elle est vraiment chargée...

Je me suis dit qu'en la refondant en NSDocument-based-application, cela me sauverait, sauf que je ne connais absolument pas le sujet, et je me suis bien perdu...

Je lu les docs d'Apple concernant le NSDocument et le chargement de vue/nib/window, et, bein boff.

Ce que je souhaiterais faire c'est avoir un NIB principal avec des "placeholders" qui seraient d'autres NIBs.

Ce que j'ai testé, en étape, c'est:

1. J'ajoute un Custom View dans mon NIB principal et je lui applique (dans Class Identity) une NSView subclassé
(voir le code plus bas...)
2. Dans le NIB à  charger, je lie la vue avec _view

Je compile, je lance, et je m'apperçois que:
1. La NIB est chargée
2. Je n'arrive pas a communiquer avec mes IBAction de la subclass depuis la NIB principale (par ex. une toolbar)

Quelqu'un pourait-il m'aiguiller vers de la doc, ou un tutoriel, ou un projet open source existant pour etudier le code?
Dans les livres de reference (Hillegass et autres) ceci n'est pas mentionné, et la doc Apple concernant le sujet n'est pas hyper limpide...  :'(

Merci d'avance...

@interface BottomView : NSView {
IBOutlet NSView *_view;
}

- (id)initWithFrame:(NSRect)frame {

self = [super initWithFrame:frame];

if ([NSBundle loadNibNamed:@BottomView owner:self])
{
[_view setFrame:[self bounds]];
[self addSubview:_view];
}

return self;
}


Réponses

  • NoNo Membre
    janvier 2009 modifié #2
    La petite incompréhension vient de la ligne [NSBundle loadNibNamed:@BottomView owner:self], ou plus exactement de self.

    Pour moi, les IBActions/IBOutlets de la suvbview doivent être reliés au même objet (un contrôleur par exemple) que la vue principale _view.
    Donc, à  la place de self, mets y l'instance (de ce contrôleur) qui possède déjà  les connexions pour _view.

    Dans le nib de la subview, pour le pseudo objet file's owner, mets en custom class la classe du contrôleur. Enfin lie les actions/outlets des objets de la subview au file's owner.

    Bien sûr, faut pas oublier de déclarer les IBActions et IBOutlets correspondants (ceux de la subview) dans le .h du contrôleur.
    Au chargement par loadNibNamed, les liaisons entre subview et contrôleur seront faites automatiquement.
  • soraya_sochsoraya_soch Membre
    08:38 modifié #3
    No,

    Merci de la réponse, j'ai mis du temps a répondre et je m'en excuse.
    Je voulais tester des choses, mais je pense m'être bien perdu dans mes idées...

    J'ai essayé ceci:
    - NSWindowController avec des NSViewController

    Pour illustrer ceci, je me permet de mettre en pièce jointe une app test...
    Dans l'exemple je n'arrive pas a lier le bouton se trouvant hors de la view Top...

    Ai-je (très/trop) mal compris?

    Merci!

    S.  :o
  • uocramuocram Membre
    08:38 modifié #4
    Dans ton appli le currentViewController correspond au bottomViewController qui ne connait pas l'action change:

    Peut-être en utilisant dans MyController.h :
    NSViewController*	topViewController;<br />	NSViewController*	bottomViewController;<br />
    

    initialisés dans l'awakeFromNib :
    topViewController = [[TopController alloc] initWithNibName:@&quot;Top&quot; bundle:nil];<br />	bottomViewController = [[BottomController alloc] initWithNibName:@&quot;Bottom&quot; bundle:nil];<br />
    


    Après tu peux utiliser :
    - (IBAction) changeLabel: (id) sender<br />{<br />	[topViewController changeLabel:sender];<br />}
    


    Etait-ce le sens de ta question?


  • soraya_sochsoraya_soch Membre
    08:38 modifié #5
    Uocram,

    >>Etait-ce le sens de ta question?

    En partie oui, ton bon sens à  éclairé mes yeux endormit...

    Je lisais des posts (et des  docs) qui insistaient sur le fait que: lorsque le File's Owner est changé en tant qu'instance du controller, il faut manuellement déclarer les IBAction dans IB, et ceux-ci doivent bien sur être nommé comme ceux des sous classes.

    Cela correspondrait alors à  [topViewController changeLabel:sender]; .

    En fait, j'avais très très (mais vraiment très) mal comprit la doc à  la lecture, et j'étais resté sur des idées erronnés...

    Merci!

    S. 

  • soraya_sochsoraya_soch Membre
    08:38 modifié #6
    Me revoilà  après un moment loin du Mac... et toujours sur le même problème.

    J'essaye toujours de comprendre comment communiquer entre mes nibs...

    J'ai:
    - Mis le MyController en File's Owner pour tous les nibs qui seront chargés dans l'appli.

    J'essaye de modifier des labels des mon nib principal et sous-nibs.

    - J'ai 2 messages m'informant qu'une connexion n'est pas possible a mes actions.
    - J'arrive a updater le label dans son nib (Top), mais pas depuis le nib parent (MyWindow.nib)
    - Je n'arrive pas a updater le label du nib Bottom

    Je dois me rendre à  l'évidence que je ne comprend pas... c'est dur d'être newbie  :'(

    J'apprécie toute aide!
  • Philippe49Philippe49 Membre
    février 2009 modifié #7
    Première chose que je vois :

    Quand on fait un xib piloté par une classe (BottomController par exemple) héritant de NSViewController, le File's Owner est défini par cette classe.
    Ainsi, dans Bottom.xib pas de cube bleu BottomController, mais File's Owner de type BottomController.

    Conséquence :
    Il faut alors réfléchir aux connexions des controls dans ce nib
    • Est-ce bien nécessaire que les contrôles soient dans ces xib ?
    • Si oui, cela peut-il être traité par le view controller (le plus simple)
    • Si non, il faut passer au-dessus par le mécanisme du first responder par exemple.
  • Philippe49Philippe49 Membre
    08:38 modifié #8
    Tu définis  @interface MyWindow : NSDocument , drôle d'idée d'appeler un document MyWindow, et  dans @implementation MyWindow.m je vois :
    - (void) awakeFromNib {
    myController = [[MyController alloc] initWithWindowNibName:@MyWindow];
    [myController showWindow:self];
    }
    ?

    Un conseil : travailles avec une Cocoa Application pour essayer la manipulation de tes multiples xib , ou bien alors il faut reprendre les chapitres de Hillegass sur les Cocoa-document based application.
  • soraya_sochsoraya_soch Membre
    08:38 modifié #9
    Merci des commentaires,

    >> drôle d'idée d'appeler un document MyWindow, et  dans @implementation MyWindow.m
    Je n'avais pas de AppDelegate lié au delegate, et le nom est un résidu d'une classe réutilisée. Mea culpa...

    • Est-ce bien nécessaire que les contrôles soient dans ces xib ?
    Tu veux dire: je design mes contrôles du XIB directement dans le code?

    • Si oui, cela peut-il être traité par le view controller (le plus simple)
    Je m'étais basé sur l'app ViewController (http://developer.apple.com/samplecode/ViewController/index.html) mais je ne vois pas où mettre les actions et comment faire communiquer les nib "enfants" au nib "parent".

    • Si non, il faut passer au-dessus par le mécanisme du first responder par exemple.
    Je croyais que c'était cela que j'avais essayé... sans succès.


    J'ai vraiment tenté de voir dans le Hillegass (Cocoa Programming for Mac OSX) mais je ne vois pas où il y a ce que je recherche.
    Ce n'est pas du view swapping, et la section concernant le Document Based Application ne mentionne pas la communication des nib entre eux...

    Je fait du sur-place... ;-(

    J'ai mis à  jour le projet, en essayant 2-3 trucs recupérés dans Hillegass... Suis-je très (trop) loin?

    Merci pour tout!

    S.



  • Philippe49Philippe49 Membre
    08:38 modifié #10
    dans 1234184470:

    mais je ne vois pas où mettre les actions et comment faire communiquer les nib "enfants" au nib "parent".

    Les nib ne communiquent pas entre eux. Ce sont des utilitaires graphiques qui remplacent l'écriture de code. Au run-time seuls existent les objets qui ont été construits à  partir du schéma que représentent ces nib.
    Ainsi, si tu crées un ViewController par initWithNibName: bundle: tous les objets contenus dans ce nib sont créés, et les connexions établies, mais le nib lui n'a plus de réalité concrète.

    @interface  MainController : NSObject  // ce que tu appelles MyWindow <br />.......<br />@end<br /> <br />@implementation MainController <br /><br />- (void) awakeFromNib {<br />   bottomController = [[BottomController alloc] initWithWindowNibName:@&quot;bottom&quot; bundle:nil];<br />   [contentView addSubview: [bottomController view]];<br />}
    


    Par contre,
    • le bottomController lui peut recevoir des messages de la part de l'instance de MainController, et des demandes d'action de la part des boutons et autres présents dans le nib "Bottom"
    • et pour peu que l'on définisse une variable mainController dans BottomCOntroller, initialisée comme suit, on pourra lors de l'appel d'une action par un bouton du nib "Bottom" faire en sorte que le BottomViewCOntroller agisse au niveau supérieur du mainController. Capito ? 
    - (void) awakeFromNib {<br />   bottomController = [[BottomController alloc] initWithWindowNibName:@&quot;bottom&quot; bundle:nil];<br />   [bottomController setValue:self forKey:@&quot;mainController&quot;];<br />   [contentView addSubview: [bottomController view]];<br />}
    



    dans 1234184470:

    Ce n'est pas du view swapping, et la section concernant le Document Based Application ne mentionne pas la communication des nib entre eux...

    Parce que les Document-Based Application sont fait pour utiliser plusieurs exemplaires de la même application, sur le modèle de TextEdit par exemple qui permet de gérer des documents différents. C'est pour cela je pense que tu ne trouveras aucune solution de ce côté-là , et que par rapport à  ce que tu sembles vouloir faire, le template à  prendre était une Cocoa-based Application.
  • mpergandmpergand Membre
    08:38 modifié #11
    [Philippe49 expose la même idée, grilled quoi !]

    Salut,

    Ton problème est que Top et Bottom n'ont pas connaissance l'un de l'autre, il faut donc trouver un objet qui les connaisse tous les deux et y a pas 50 solutions c'est ton document.

    Donc, quand tu crées tes viewControllers, il faut que tu ajoutes un paramètre pour ton document, à  partir de Top, tu demanderas à  ton document de changer tel objet de Bottom.


    Maintenant, il y a une possibilité d'accéder à  tout objet d'une vue grâce au tags (à  fixer dans IB).
    <br />// à  partir de Top, on recherche le textField tag 100 dans Bottom<br /><br />NSView* contentView=[[self window] contentView];<br /><br />NSTextField* label=[contentView viewWithTag:100];<br /><br />
    

  • soraya_sochsoraya_soch Membre
    08:38 modifié #12
    >> Les nib ne communiquent pas entre eux.
    :crackboom:- Je l'ai lu 1000x en plus...


    Merci à  vous deux pour toutes ces infos... j'ai de quoi approfondir 



  • soraya_sochsoraya_soch Membre
    08:38 modifié #13
    Voici ce que à  quoi je suis arrivé...  :-\\

    C'est mieux sensei?

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