Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mac OS X Cocoa multiview application navigation

I've already spent 2 full days trying to figure out how to use NSViewControllers in order to create a multiview application.

Here is what I do.

I have 2 View Controllers and the MainMenu.xib's Window. I also have an AppController that is the delegate for both View Controllers.

When I launch the app, I'm first greeted with the MainMenu.xib's Window's view which holds a button. On clicking this button, an IBAction is sent to the appController and asks for the SecondViewController to display it's nib. So far, everything's fine and the nib file is displayed correctly.

On the secondViewController, there's another button that sends another IBAction to the appController and asks for the FirstViewController to be displayed but nothing happens, no crash, no warning... Any help would be much appreciated... Thanks in advance for your patience...

Here is the code for the 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

and here is the code for the 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

Well, anyone can help me, I just need a single view application that displays a first ViewController with a button on the first viewController that takes me to a second view controller with a second button that takes me back to my first viewcontroller... I've already spent more than a week on that... in vain... PS : I don't want any button on the mainMenu.xib window nor tabs.

like image 978
Miky Mike Avatar asked Feb 14 '13 23:02

Miky Mike


1 Answers

here is the solution to my question then.

Here's the code for the 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

Now, here's the 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

Next we need to set delegates in the FirstViewController and the 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

And here is the 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

Now, same thing for the 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

And here's the 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

Well, I guess this code may be improved and if you have any suggestion, feel free to let me know. Hope it will help others.

like image 80
Miky Mike Avatar answered Oct 05 '22 19:10

Miky Mike