我已经花了整整2天试图弄清楚如何使用NSViewControllers来创建一个多视图应用程序。
这就是我的工作。
我有2个View Controllers和MainMenu.xib的Window。 我还有一个AppController,它是两个视图控制器的委托。
当我启动应用程序时,我首先会遇到MainMenu.xib的Window视图,其中包含一个按钮。单击此按钮,IBAction将发送到appController并要求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窗口上显示任何按钮,也不需要标签。
答案 0 :(得分:4)
这是我的问题的解决方案。
以下是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
嗯,我想这段代码可能会有所改进,如果您有任何建议,请随时告诉我。希望它能帮助别人。
答案 1 :(得分:1)
问题:当用户按下View2中的按钮时,您希望显示View1。不是。
步骤1:您说按钮应在AppController上调用操作。在该操作中设置断点(或添加诊断日志),只是为了验证它实际上是否被调用。
第2步:准确地思考你想要采取什么行动。我的猜测是你要隐藏View2并显示View1。也许
[view2 setHidden: YES];
[view1 setHidden: NO];
(当然,我不是在这里使用你的名字。)或者你可以为过渡设置动画,交叉淡化视图或移动它们。
第3步:我的猜测是第2步将解决您的问题。如果没有,请再次使用调试器来验证view1和view2不为null。 (如果它们是空的,你可能有弱变量,你需要它们变强。)
步骤4:万一你仍然卡住,检查view1和view2的帧。也许view1不在你想象的地方。
步骤5:如果您仍然卡住,请检查view1的alphaValue。也许你将它设置为透明,并且它在正确的位置透明地绘制。
第6步:我打赌没有第6步!
答案 2 :(得分:0)
目前这不是一个很好的答案,但是我对你想要与你合作的代码有些担忧。
您确定已在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;