Mac OS X Cocoa multiview application navigation

后端 未结 3 1931
一生所求
一生所求 2020-12-28 23:50

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 Vie

相关标签:
3条回答
  • 2020-12-29 00:34

    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.

    0 讨论(0)
  • 2020-12-29 00:37

    THE PROBLEM: When the user presses a button in View2, you want View1 to appear. It's not.

    STEP 1: You say that the button should be invoking an action on your AppController. Set a breakpoint (or add a diagnostic log) in that action, just to verify that it is, in fact, being invoked.

    STEP 2: Think about what you want that action to do, precisely. My guess is that you want to hide View2 and show View1. Perhaps

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

    (I'm not using your names here, of course.) Or you might animate the transitions, either cross-fading the views or moving them.

    STEP 3: My guess is that STEP 2 will solve your problem. If it doesn't, use the debugger again to verify that view1 and view2 are not null. (If they're null, you probably have weak variables where you need them to be strong.)

    STEP 4: In the unlikely event that you're still stuck, check the frames of view1 and view2. Perhaps view1 isn't where you think it is.

    STEP 5: If you're still stuck, check the alphaValue of view1. Maybe you set it to be transparent, and it's being drawn transparently in the right place.

    STEP 6: I bet there is no step 6!

    0 讨论(0)
  • 2020-12-29 00:43

    This isn't much of an answer at the moment, however I have some concerns about your code that I wanted to work through with you.

    • Are you sure you have connected the outlets and actions in Interface Builder. Please verify this.

    • You don't need mainWindow as there is already a window property that points to the main window (verify this in Interface Builder). Also this looks wrong:

      @synthesize mainWindow = mainwindow;
                                   ^
                                   W
      

      So dump that and just use the existing window outlet provided by Xcode.

    • Don't re-create the view controllers if they already exist:

      if (self.secondViewController == nil)
      {
          self.secondViewController = [[SecondViewController alloc] initWithNibName:@"SecondViewController"
                                                                             bundle:nil];
      }
      self.window.contentView = self.secondViewController.view;
      
    0 讨论(0)
提交回复
热议问题