如何在程序启动期间从自定义类初始化主窗口对象?

时间:2015-04-25 20:10:34

标签: objective-c cocoa

我有一个带有几个弹出按钮的主窗口。我想清除它们,然后从自定义类中的方法加载列表。我的视图控制器工作正常,我知道自定义类(newRequest)中的方法正常工作,因为我在方法执行时添加了一个NSLog命令来打印“Test”。在AppDelegate中,我通过以下方式调用方法: [polyAppRequest newRequest];。 正如我所说,我知道该方法正在执行。为什么我不能从这个自定义类方法中弹出popupbutton中的allitems? 谢谢 基思

1 个答案:

答案 0 :(得分:0)

我读到你应该使用NSWindowController来管理一个窗口。见这里:

Windows and window controllers

Adding views or windows to MainWindow

然后,如果你的窗口变得足够复杂,NSWindowController可以使用各种NSViewControllers来管理部分窗口。

无论如何,我在答案中使用了NSWindowController。

下面的图片显示了文件所有者的出口,即MainWindowController

enter image description here

我在Xcode6.2创建了MainWindowController .h / .m:

  1. 选择文件>新建>文件> OS X - 来源 - Cocoa Class
  2. Subclass of:
  3. 选择NSWindowController
  4. 正在检查also create .xib file for user interface
  5. 然后我在默认的MainMenu.xib中删除了窗口 - 而不是菜单 - 我将上面步骤创建的MainWindowController.xib的名称更改为MainWindow.xib。

    以下代码适用于我(但我是Cocoa初学者!):

    //
    //  AppDelegate.m
    //  PopUpButtons
    
    #import "AppDelegate.h"
    #import "MainWindowController.h"
    
    @interface AppDelegate ()
    
    @property(strong) MainWindowController* mainWindowCtrl;
    
    @end
    
    
    @implementation AppDelegate
    
    
    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
        // Insert code here to initialize your application
    
        [self setMainWindowCtrl:[[MainWindowController alloc] init]];
        [[self mainWindowCtrl] showWindow:nil];
    }
    
    - (void)applicationWillTerminate:(NSNotification *)aNotification {
        // Insert code here to tear down your application
    }
    
    @end
    

    ...

    //
    //  MainWindowController.m
    //  PopUpButtons
    //
    
    #import "MainWindowController.h"
    #import "MyData.h"
    
    @interface MainWindowController ()
    
    @property(strong) MyData* data;
    @property(weak) IBOutlet NSPopUpButton* namePopUp;
    @property(weak) IBOutlet NSPopUpButton* agePopUp;
    
    @end
    
    
    @implementation MainWindowController
    
    -(id)init {
    
        if (self = [super initWithWindowNibName:@"MainWindow"]) {
            _data = [[MyData alloc] init];  //Get data for popups
        }
    
        return self;
    }
    
    - (void)windowDidLoad {
        [super windowDidLoad];
    
        // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
    
        [[self namePopUp] removeAllItems];
        [[self namePopUp] addItemsWithTitles:[[self data] drinks]];
        [[self agePopUp] removeAllItems];
        [[self agePopUp] addItemsWithTitles:[[self data] extras]];
    }
    
    @end
    

    ...

    //
    //  MyData.h
    //  PopUpButtons
    //
    
    #import <Foundation/Foundation.h>
    
    @interface MyData : NSObject
    
    @property NSArray* drinks;
    @property NSArray* extras;
    
    @end
    

    ...

    //
    //  MyData.m
    //  PopUpButtons
    //
    
    #import "MyData.h"
    
    @implementation MyData
    
    - (id)init {
        if (self = [super init]) {
            _drinks = @[@"coffee", @"tea"];
            _extras = @[@"milk", @"sugar", @"honey"];
        }
    
        return self;
    
    }
    
    @end
    

    我希望有所帮助。如果您需要更多屏幕截图,请与我们联系。

    <强> EDIT1:

    我想我知道你在问什么。虽然我不认为这是一个非常好的方法,但如果我将代码更改为:

    //
    //  MyData.h
    //  PopUpButtons
    //
    
    #import <Cocoa/Cocoa.h>
    
    @interface MyData : NSObject
    
    @property (copy) NSArray* drinks;
    @property (copy) NSArray* extras;
    
    -(void)newRequest;
    
    @end
    

    ...

    //
    //  MyData.m
    //  PopUpButtons
    //
    
    #import "MyData.h"
    
    @interface MyData()
    
    @property (weak) IBOutlet NSPopUpButton* drinksPopUp;
    @property (weak) IBOutlet NSPopUpButton* extrasPopUp;
    
    @end
    
    
    @implementation MyData
    
    - (id)init {
        if (self = [super init]) {
            _drinks = @[@"coffee", @"tea"];
            _extras = @[@"milk", @"sugar", @"honey"];
        }
    
        return self;
    
    }
    
    
    -(void)newRequest {
        [[self drinksPopUp] removeAllItems];
        [[self drinksPopUp] addItemsWithTitles:[self drinks]];
    
        [[self extrasPopUp] removeAllItems];
        [[self extrasPopUp] addItemsWithTitles:[self extras]];
    }
    
    @end
    

    我无法填充NSPopUpButtons。这就是我所做的:

    1. 我将一个Object从Object Library拖到IB中的dock,在Identity Inspector中,我将Object的类更改为MyData。

    2. 然后我点击了Connections Inspector,并在Outlets中列出了MyData,drinkPopUp和extrasPopUp中的两个实例变量。

    3. 我从出口拖到相应的NSPopUpButtons。

    4. 我想我和你一样认为,当我的程序运行时,NSPopUpButtons会被分配给实例变量drinkPopUp和extrasPopUp--但似乎并非如此。根据{{​​3}},您应该可以这样做:

        

      应用程序通常在其自定义之间设置插座连接   用户界面上的控制器对象和对象,但它们可以   在任何可以表示为实例的对象之间进行的   Interface Builder,...

      <强> EDIT2:

      我能够将NSPopUpButtons从我的MainWindowController传递给newRequest方法,我可以使用newRequest中的NSPopUpButtons来成功填充数据。

      <强> EDIT3:

        

      我知道自定义类(newRequest)中的方法正在工作,因为   我添加了一个NSLog命令来打印&#34;测试&#34;当方法执行时。

      但是当您记录指向NSPopUpButtons的变量时会发生什么?使用Edit1中的代码,我得到变量的NULL,这意味着NSPopUpButtons永远不会被分配给变量。

      <强> Edit4

      如果我向MyData添加awakeFromNib方法,并且在awakeFromNib中我记录了Edit1中代码的NSPopUpButton变量,我得到非NULL值。这告诉我MainWindowController的windowDidLoad方法在MyData的awakeFromNib方法之前执行,因此你不能在MainWindowController的windowDidLoad方法中调用newRequest,因为MyData还没有完全初始化。

      <强> Edit5

      好的,我在Edit1中获得了代码。 Apple docs说出这个:

        

      关于顶级对象

           

      当程序加载nib文件时,Cocoa会重新创建整个图形   您在Xcode中创建的对象。该对象图包括所有   找到的窗口,视图,控件,单元格,菜单和自定义对象   nib文件。顶级对象是这些对象的子集   没有父对象[在IB中]。通常是顶级对象   仅包括窗口,菜单栏和自定义控制器对象   你添加到nib文件[像MyData对象]。 (File's Owner,First等对象   响应者和应用程序是占位符对象,不予考虑   顶级对象。)

           

      通常,您使用File的Owner对象中的outlet来存储   引用nib文件的顶级对象。如果不使用   但是,您可以从中检索顶级对象   nib-loaded例程直接。你应该总是保持一个指针   这些对象因为您的应用程序负责而在某处   使用它们时释放它们。有关的更多信息   加载时的nib对象行为,请参阅管理生命周期   来自Nib文件的对象。

      按照上面的粗线,我在MainWindowController.m中更改了这个声明:

      @interface MainWindowController ()
      
      @property(strong) MyData* data;
      ...
      
      @end
      

      到此:

      @interface MainWindowController ()
      
      @property(strong) IBOutlet MyData* data;
      ...
      
      @end
      

      然后,在IB中,我将一个连接从MainWindowController 数据插件拖到MyData对象(我以前从对象库中拖出的对象和文档)。

      我想这会导致MyData从.xib文件中取消归档并在MainWindowController之前初始化。