2013-02-14 31 views
5

Ho già trascorso 2 giorni interi a cercare di capire come utilizzare NSViewControllers per creare un'applicazione multiview.Navigazione applicazione multiview Coco OS Mac OS X

Ecco cosa faccio.

Sono presenti 2 controller di visualizzazione e la finestra di MainMenu.xib. Ho anche un AppController che è il delegato per entrambi i View Controller.

Quando avvio l'app, per prima cosa sono accolto con la vista della finestra di MainMenu.xib che contiene un pulsante. Facendo clic su questo pulsante, IBAction viene inviato a appController e chiede al SecondViewController di visualizzarlo. Finora, tutto è a posto e il file del pennino viene visualizzato correttamente.

Sul secondViewController, c'è un altro pulsante che invia un'altra IBAction al AppController e chiede la FirstViewController da visualizzare, ma non succede nulla, nessun incidente, nessun avviso ... Qualsiasi aiuto sarebbe molto apprezzato ... Grazie in anticipo per la vostra pazienza ...

Ecco il codice per l'AppController.h:

#import <Foundation/Foundation.h> 
#import "SecondViewController.h" 
#import "FirstViewController.h" 

@interface AppController : NSObject 

@property (strong) IBOutlet NSWindow *mainWindow; 

@property (strong) IBOutlet SecondViewController *secondViewController; 
@property (strong) IBOutlet FirstViewController *firstViewController; 


- (IBAction)secondButtonfromsecondViewControllerClicked:(id)sender; 

- (IBAction)buttonClicked:(id)sender; 

@end 

e qui è il codice per l'AppController.m:

#import "AppController.h" 


@implementation AppController 
@synthesize mainWindow = mainwindow; 
@synthesize secondViewController; 
@synthesize firstViewController; 

- (IBAction)buttonClicked:(id)sender { 

    NSLog(@"button from second View Controller clicked"); 

    self.secondViewController = [[SecondViewController 
    alloc]initWithNibName:@"SecondViewController" bundle:nil]; 
    self.mainWindow.contentView = self.secondViewController.view; 
    [self.secondViewController.view setAutoresizingMask:NSViewWidthSizable | 
    NSViewHeightSizable]; 
} 

- (IBAction)secondButtonfromsecondViewControllerClicked:(id)sender { 

    NSLog(@"button from first ViewController clicked"); 

    self.firstViewController = [[FirstViewController 
    alloc]initWithNibName:@"FirstViewController" bundle:nil]; 
    self.mainWindow.contentView = [self.firstViewController view]; 

} 


@end 

Bene, chiunque può aiutarmi, ho solo bisogno di un'applicazione a vista singola che visualizza un primo ViewController con un pulsante sulla prima viewController che mi porta a un secondo controller di vista con un secondo pulsante che mi riporta al mio primo viewcontroller ... Ho già trascorso più di una settimana su questo ... invano ... PS: Non voglio nessun pulsante sulla finestra mainMenu.xib né sulle schede.

+0

Un motivo particolare per cui si desidera utilizzare un controller di visualizzazione (a parte forse essere utilizzato per utilizzarli in iOS)? Sembra un lavoro perfetto per una visualizzazione a schede. O anche solo scambiando le viste a livello di programmazione. – Monolo

+0

OK, e hai controllato l'ovvio; l'azione non è collegata all'interno di Interface Builder? – trojanfoe

+0

Waouh, almeno alcune risposte ... –

risposta

4

ecco la soluzione alla mia domanda allora.

Ecco il codice per l'AppDelegate.h:

// AppDelegate.h 


#import <Cocoa/Cocoa.h> 
#import "FirstViewController.h" 
#import "SecondViewController.h" 

//We need to declare the AppDelegate class as being the delegate for both 
//FirstViewController and SecondViewController 

@interface AppDelegate : NSObject <NSApplicationDelegate, 
FirstViewControllerDelegate, SecondViewControllerDelegate> 

@property (strong, nonatomic) NSWindow *window; 
@property (strong) FirstViewController *firstViewController; 
@property (strong) SecondViewController *secondViewController; 

-(void) goToSecondView; 
-(void) goToFirstView; 

@end 

Ora, ecco l'AppDelegate.m:

// AppDelegate.m 

#import "AppDelegate.h" 


@implementation AppDelegate 

@synthesize window = _window; 
@synthesize firstViewController; 
@synthesize secondViewController; 

-(void) awakeFromNib { 

[self goToFirstView]; 
self.firstViewController.delegate = self; 

} 


-(void) goToSecondView { 

     if (self.secondViewController ==nil) { 
      self.secondViewController =[[SecondViewController alloc] 
      initWithNibName:@"SecondViewController" bundle:nil]; 
     } 

     self.window.contentView = [self.secondViewController view]; 
    } 

-(void) goToFirstView { 

if (self.firstViewController ==nil) { 
    self.firstViewController =[[FirstViewController alloc] 
    initWithNibName:@"FirstViewController" bundle:nil]; 
    } 

    self.window.contentView = [self.firstViewController view]; 

} 

@end 

Poi abbiamo bisogno di impostare i delegati nel FirstViewController e la SecondViewController

// FirstViewController.h 

#import <Cocoa/Cocoa.h> 
#import "SecondViewController.h" 

//We declare the delegation protocole: 

@protocol FirstViewControllerDelegate <NSObject> 

-(void)goToSecondView; 

@end 

@interface FirstViewController : NSViewController 

- (IBAction)firstViewControllerButtonClicked:(id)sender; 

@property (nonatomic, strong) id <FirstViewControllerDelegate> delegate; 

@end 

Ed ecco il FirstViewController.m:

// FirstViewController.m 

#import "FirstViewController.h" 

@implementation FirstViewController 
@synthesize delegate; 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{ 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) { 

    self.delegate = [NSApp delegate]; 

    } 

    return self; 
} 

- (IBAction)firstViewControllerButtonClicked:(id)sender { 

    NSLog(@"button from first View Controller clicked"); 

    if ([self.delegate respondsToSelector:@selector(goToSecondView)]) { 
    [self.delegate goToSecondView]; 
    } 
} 

@end 

Ora, stessa cosa per il SecondViewController:

// SecondViewController.h 

#import <Cocoa/Cocoa.h> 

@protocol SecondViewControllerDelegate <NSObject> 

-(void)goToFirstView; 

@end 

@interface SecondViewController : NSViewController 

@property (nonatomic, strong) id <SecondViewControllerDelegate> delegate; 

- (IBAction)goToFirstViewControllerButtonClicked:(id)sender; 

@end 

Ed ecco il SecondViewController.m:

// SecondViewController.m 

    #import "SecondViewController.h" 

    @interface SecondViewController() 

    @end 

    @implementation SecondViewController 

    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{ 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) { 

     self.delegate = [NSApp delegate]; 
    } 

    return self; 
    } 

    - (IBAction)goToFirstViewControllerButtonClicked:(id)sender { 

    NSLog(@"button from Second View Controller clicked"); 

    if ([self.delegate respondsToSelector:@selector(goToFirstView)]) { 
    [self.delegate goToFirstView]; 
    } 

} 
@end 

Beh, credo che questo codice può essere migliorata e se avete qualche suggerimento , sentiti libero di farmelo sapere. Spero che aiuti gli altri.

+1

Il tuo codice non funziona. – zzzzz

0

Al momento non è più una risposta, tuttavia nutro qualche preoccupazione sul proprio codice che volevo elaborare con voi.

  • Sei sicuro di aver collegato le prese e le azioni in Interface Builder. Si prega di verificare questo.

  • Non è necessario mainWindow in quanto esiste già una proprietà window che punta alla finestra principale (verificarlo in Interface Builder). Anche questo sembra sbagliato:

    @synthesize mainWindow = mainwindow; 
              ^
              W 
    

    Così dump e basta usare la window presa esistente fornito da Xcode.

  • Non ricreare il controller di vista se già esistono:

    if (self.secondViewController == nil) 
    { 
        self.secondViewController = [[SecondViewController alloc] initWithNibName:@"SecondViewController" 
                         bundle:nil]; 
    } 
    self.window.contentView = self.secondViewController.view; 
    
+0

Il motivo per cui desidero utilizzare ViewControllers è che voglio trasferire la mia app Iphone sul Mac e voglio utilizzare una vista diversa per ogni attività. La vera domanda è: come posso navigare tra i ViewControllers e caricare le loro viste all'interno della finestra del contenuto della finestra di MainMenu.xib al livello programmatico dall'interno del codice dei miei viewcontrollers? Su IOS, avevo un RootViewController e un controller di navigazione ma non c'è un controller di navigazione per MAC ... Inoltre, non ho codificato una singola linea in tre anni, quindi non sono nemmeno sicuro di sapere cosa collegare all'interno di IB. –

+0

Vado a controllare. Grazie ... –

+0

Se rimuovo la proprietà mainWindow all'interno della classe AppController, non so come chiamare contentView della finestra mainMenu.xib da AppController.Non capisco "Non hai bisogno di mainWindow in quanto esiste già una proprietà della finestra che punta alla finestra principale". Quando avevo la proprietà MainWindow all'interno dell'appController, potevo usarla per visualizzare la prima viewController, ora sono in perdita senza quella proprietà. Dovrei usare super? Il problema sembra essere con mainWindow il cui valore è 00000 nella modalità di debug passo dopo passo. –

1

IL PROBLEMA: Quando l'utente preme un pulsante nella View2, si desidera visualizzare View1. Non è.

FASE 1: Si dice che il pulsante deve invocare un'azione sul proprio AppController. Impostare un punto di interruzione (o aggiungere un registro diagnostico) in quell'azione, solo per verificare che sia, di fatto, invocato.

FASE 2: pensa a cosa vuoi che quell'azione faccia, precisamente. La mia ipotesi è che tu voglia nascondere View2 e mostrare View1. Forse

[view2 setHidden: YES]; 
[view1 setHidden: NO]; 

(non sto usando i vostri nomi qui, naturalmente.) O si potrebbe animare le transizioni, o dissolvenza incrociata il punto di vista o in movimento.

PASSO 3: La mia ipotesi è che STEP 2 risolverà il problema. In caso contrario, utilizzare di nuovo il debugger per verificare che view1 e view2 non siano nulli. (Se sono nulli, probabilmente hai variabili deboli in cui devi essere forte.)

PASSO 4: Nell'improbabile caso in cui tu sia ancora bloccato, controlla i fotogrammi di view1 e view2. Forse view1 non è dove pensi che sia.

PASSO 5: Se sei ancora bloccato, controlla il valore alpha della vista1. Forse lo hai impostato per essere trasparente, e viene disegnato in modo trasparente nel posto giusto.

PASSO 6: scommetto che non c'è passaggio 6!

+0

Grazie per il tuo suggerimento ma non è quello che volevo fare . Ho trovato un modo per implementare ciò che volevo fare usando i delegati che rendono il AppDelegate caricare ViewControllers. Il fatto è che non avevo codificato nulla in tre anni, quindi mi ci è voluto del tempo per implementarlo. Dopo averne letto ancora, sta finalmente funzionando! Grazie a tutti voi ragazzi comunque. –