2013-02-14 4 views
5

Я уже провел 2 полных дня, пытаясь выяснить, как использовать NSViewControllers для создания приложения с несколькими видами.Mac OS X Cocoa multiview application navigation

Вот что я делаю.

У меня есть 2 контроллера просмотра и окно MainMenu.xib. У меня также есть AppController, который является делегатом для обоих контроллеров View.

Когда я запускаю приложение, меня сначала приветствует вид окна MainMenu.xib, который содержит кнопку. При нажатии этой кнопки IBAction отправляется в appController и просит SecondViewController отображать его. Пока все в порядке, и файл 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, который выводит меня на второй контроллер представления со второй кнопкой, которая возвращает меня к моему первому диспетчеру просмотра ... Я уже потратил больше недели на это ... зря ... PS: Я не хочу никакой кнопки в окне mainMenu.xib и вкладок.

+0

Любая конкретная причина, по которой вы хотите использовать контроллер вида (кроме, возможно, использования их в iOS)? Это звучит как идеальная работа для просмотра табуляции. Или даже просто подменю взглядов программно. – Monolo

+0

ОК, и вы проверили очевидное; действие не связано в Interface Builder? – trojanfoe

+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

Ваш код не работает. – zzzzz

0

Это не очень важный ответ на данный момент, однако у меня есть некоторые сомнения относительно вашего кода, с которым я хотел работать с вами.

  • Удостоверьтесь, что вы подключили выходы и действия в Interface Builder. Пожалуйста, проверьте это.

  • Не требуется mainWindow, так как уже есть свойство window, которое указывает на главное окно (проверьте это в Interface Builder). Кроме того, это выглядит не так:

    @synthesize mainWindow = mainwindow; 
              ^
              W 
    

    Так свалка, что и просто использовать существующий window выход предоставленный Xcode.

  • Не воссоздавать контроллеры просмотра, если они уже существуют:

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

Причина, по которой я хочу использовать ViewControllers, заключается в том, что я хочу портировать приложение Iphone на Mac, и я хочу использовать разные представления для каждой задачи. Реальный вопрос: как я могу перемещаться между ViewControllers и загружать их взгляды в программном обеспечении окна MainMenu.xib программно изнутри кода моих контроллеров view? В IOS у меня был RootViewController и контроллер навигации, но нет контроллера навигации для MAC ... Более того, я не кодировал одну строку за три года, поэтому я даже не уверен, что знаю, что нужно связывать внутри IB. –

+0

Я собираюсь проверить. Спасибо ... –

+0

Если я удалю свойство mainWindow внутри класса AppController, я не знаю, как вызвать contentView.exe из основного приложения AppMontroller.Я не понимаю: «Вам не нужен mainWindow, поскольку уже есть свойство окна, которое указывает на главное окно». Когда у меня было свойство mainWindow внутри appController, я мог бы использовать его для отображения первого viewController, теперь я теряюсь без этого свойства. Должен ли я использовать супер? Кажется, что проблема связана с mainWindow, значение которого составляет 00000 в пошаговом режиме отладки. –

1

ПРОБЛЕМА: Когда пользователь нажимает кнопку в View2, вы хотите View1 появляться. Это не.

ШАГ 1: Вы говорите, что кнопка должна вызывать действие на вашем AppController. Установите контрольную точку (или добавьте журнал диагностики) в это действие, чтобы убедиться, что она фактически вызвана.

ШАГ 2: Подумайте о том, что вы хотите, чтобы это действие было точно. Я предполагаю, что вы хотите скрыть View2 и показать View1. Возможно

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

(я не использую свои имена здесь, конечно.) Или вы можете анимировать переходы, либо затенение точки или перемещение их.

ШАГ 3: Я предполагаю, что STEP 2 решит вашу проблему. Если это не так, снова используйте отладчик, чтобы убедиться, что view1 и view2 не являются нулевыми. (Если они ноль, у вас, вероятно, есть слабые переменные, где вам нужно, чтобы они были сильными.)

ШАГ 4: В маловероятном случае, когда вы все еще застряли, проверьте рамки view1 и view2. Возможно, view1 - это не то место, где вы думаете.

ШАГ 5: Если вы все еще застряли, проверьте альфа-версию view1. Возможно, вы настроили его прозрачным, и его прозрачно рисуют в нужном месте.

ШАГ 6: Готов поспорить, нет шага 6!

+0

Спасибо за ваше предложение, но это не то, что я хотел сделать , Я нашел способ реализовать то, что я хотел сделать, используя делегаты, которые заставляют Appdelegate загружать ViewControllers. Дело в том, что за три года я ничего не закодировал, поэтому мне потребовалось некоторое время для его реализации. Прочитав еще немного, он работает наконец! Спасибо всем вам, ребята, в любом случае. –