【问题标题】:Mac OS X Cocoa multiview application navigationMac OS X Cocoa 多视图应用程序导航
【发布时间】:2013-01-30 21:49:04
【问题描述】:

我已经花了整整 2 天的时间试图弄清楚如何使用 NSViewControllers 来创建多视图应用程序。

这就是我的工作。

我有 2 个视图控制器和 MainMenu.xib 的窗口。 我还有一个 AppController,它是两个视图控制器的委托。

当我启动应用程序时,首先映入眼帘的是 MainMenu.xib 的窗口视图,其中包含一个按钮。单击此按钮时,会向 appController 发送 IBAction 并要求 SecondViewController 显示它的 nib。至此,一切正常,nib文件显示正确。

在 secondViewController 上,有另一个按钮将另一个 IBAction 发送到 appController 并要求显示 FirstViewController 但没有任何反应, 没有崩溃,没有警告......任何帮助将不胜感激...... 提前感谢您的耐心等待...

这是 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

这里是 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

好吧,任何人都可以帮助我,我只需要一个单视图应用程序,它显示第一个 ViewController,第一个 viewController 上的按钮将我带到第二个视图控制器,第二个按钮将我带回我的第一个 viewcontroller。 ..我已经花了一个多星期的时间......徒劳无功...... PS:我不想要 mainMenu.xib 窗口或选项卡上的任何按钮。

【问题讨论】:

  • 您想要使用视图控制器的任何特殊原因(除了可能习惯在 iOS 中使用它们)?这听起来像是一个标签视图的完美工作。甚至只是以编程方式交换视图。
  • 好的,你已经检查了明显的;该操作未在 Interface Builder 中连接?
  • 哇,至少有一些答案......

标签: cocoa multiview nsviewcontroller


【解决方案1】:

这就是我的问题的解决方案。

这是 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

现在,这是 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

接下来我们需要在 FirstViewController 和 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

这里是 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

现在,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

这是 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

好吧,我想这段代码可能会得到改进,如果您有任何建议,请随时告诉我。希望对其他人有所帮助。

【讨论】:

    【解决方案2】:

    问题:当用户在 View2 中按下按钮时,您希望 View1 出现。不是。

    第 1 步:您说按钮应该在您的 AppController 上调用一个操作。在该操作中设置断点(或添加诊断日志),只是为了验证它实际上正在被调用。

    第 2 步:准确地考虑您希望该操作做什么。我的猜测是你想隐藏 View2 并显示 View1。也许

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

    (当然,我在这里没有使用您的名字。)或者您可以为过渡设置动画,或者交叉淡化视图或移动它们。

    第 3 步:我猜第 2 步将解决您的问题。如果不是,请再次使用调试器来验证 view1 和 view2 是否不为空。 (如果它们为空,你可能有弱变量需要它们变强。)

    第 4 步:万一您仍然卡住,请检查 view1 和 view2 的框架。也许 view1 不是你想的那样。

    第 5 步:如果仍然卡住,请检查 view1 的 alphaValue。也许您将它设置为透明,并且它在正确的位置被透明地绘制。

    第 6 步:我敢打赌没有第 6 步!

    【讨论】:

    • 感谢您的建议,但这不是我想做的。我找到了一种方法来实现我想要使用使 Appdelegate 加载 ViewControllers 的委托。事实上,我已经三年没有编写任何代码了,所以我花了一些时间来实现它。在阅读了更多之后,它终于开始工作了!无论如何感谢你们所有人。
    【解决方案3】:

    目前这不是一个很好的答案,但是我对你的代码有些担心,我想和你一起解决。

    • 您确定已在 Interface Builder 中连接了出口和操作。请验证这一点。

    • 您不需要mainWindow,因为已经有一个指向主窗口的window 属性(在Interface Builder 中验证这一点)。这看起来也不对:

      @synthesize mainWindow = mainwindow;
                                   ^
                                   W
      

      所以转储它并使用 Xcode 提供的现有 window 插座。

    • 如果视图控制器已经存在,不要重新创建它们:

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

    【讨论】:

    • 我想使用 ViewControllers 的原因是我想将我的 Iphone 应用程序移植到 Mac 上,并且我想为每个任务使用不同的视图。真正的问题是如何在 ViewControllers 之间导航并从我的 viewcontrollers 代码内部以编程方式将它们的视图加载到 MainMenu.xib 窗口的 contentview 中?在 IOS 上,我有一个 RootViewController 和一个导航控制器,但没有用于 MAC 的导航控制器......此外,我已经三年没有编写过一行代码,所以我什至不确定我是否知道在 IB 中链接什么。
    • 如果我删除了AppController类里面的mainWindow属性,我就不知道怎么从AppController调用mainMenu.xib的window的contentView了。我不明白“您不需要 mainWindow,因为已经有一个指向主窗口的窗口属性”。当我在 appController 中拥有 mainWindow 属性时,我可以使用它来显示第一个 viewController,现在我在没有该属性时不知所措。我应该使用 super 吗?问题似乎出在逐步调试模式下值为 00000 的 mainWindow 上。
    • 你现在应该使用self.window,而不是self.mainWindow
    • 在对象类型“AppController”上找不到属性“窗口”
    • 这听起来不对。我的理解是 Xcode 生成了一个带有 window 属性的应用程序。您可以通过右键单击左侧窗格中的窗口并查看它是否连接到任何东西来在 IB 中进行验证。否则你可能不得不收回你的mainWindow 连接并忽略我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多