-1

我正在为 OS X 开发一个应用程序,但遇到了一个问题。

该应用程序的结构是:

  • AppDelegate:主要操作发生在 MainMenu.xib 中。它也是创建主窗口的地方。

  • SettingsWindowController:设置窗口是使用 SettingsWindow.xib 中的接口定义的。

  • 我创建了一个协议 SettingsWindowProtocol 来委派这两个类。

  • 我又创建了一个类 dbHandler,它dbh在 AppDelegate 中被初始化为一个 obj。

  • 在 SettingsWindowProtocol 中,我创建了一个发送对象的方法,但是在 SettingsWindowControl 中调用此方法后,该对象为空。

问题是我如何在两个不同的类中共享同一个对象?

与问题相关的一些代码块:

AppDelegate.h:

#import "dbHandler.h"    

...

@property (retain) dbHandler *dbh;
@interface AppDelegate : NSObject <SettingsWindowControllerProtocol>

-(dbHandler*)sendDBobject;

AppDelegate.m:

...
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{   
    dbh = [[dbHandler alloc]init];
    ...
}

- (IBAction)settingsButton:(id)sender {
    if(!settingsWindowController){
        settingsWindowController = [[SettingsWindowController alloc] initWithWindowNibName:@"SettingsWindow"];
    }

    [settingsWindowController showWindow:self];
    settingsWindowController.delegate = self;
}

-(dbHandler*)sendDBobject{
    return dbh;
}

设置窗口控制器.h:

#import "dbHandler.h"

@protocol SettingsWindowControllerProtocol<NSObject>
    -(dbHandler*)sendDBobject;
@end

@interface SettingsWindowController : NSWindowController

@property (assign) id<SettingsWindowControllerProtocol> delegate;

@property (retain) dbHandler* dbh;

@end

设置窗口控制器.m:

- (void)windowDidLoad
{
    dbh = [delegate sendDBobject];
    [super windowDidLoad];
    NSLog(@"settings string returned: %@",[dbh returnString]);
}
4

2 回答 2

1

看起来您在应用程序中做出了一些错误的设计选择。您不仅要调用应用程序委托来获取 dbh,而且您似乎还有一个方法可以响应操作消息 ( settingsButton:)。通常,应用程序委托是应用程序的委托 - 响应委托方法。当它做得更多时,这是一个缺乏经验的开发人员的标志;我经常看到新开发人员将应用程序委托用作方便的单例对象,他们可以在其中存储数据或方法,而不是以更面向对象的方式进行。

Xcode 应用程序模板在 AppDelegate 中初始化 Core Data Stack 并没有帮助,许多教程使用委托作为存储,因为它使项目专注于教程的主题,而不是通过按他们的方式做事来增加复杂性在现实世界中完成。

请记住,您希望代表尽可能少地做事。因此,让应用程序委托设置最少数量的对象,将它们连接在一起并让开。

在您的情况下,我看到您可以做得更好的两件事。与其设置一个协议来调用你的应用程序委托来获取一个对象,不如将它发送到堆栈上到视图控制器。其次,您的应用程序委托中有一个操作方法,这在视图控制器中会更好。因为我不想过多地进入第二个,并且您的问题是关于共享对象;以下是如何在不使用协议的情况下将对象向上传递到堆栈。

在 AppDelegate.m

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // This is okay, although it's preferable to be explicit with properties
    self.dbh = [[dbHandler alloc] init];
    ... 
}

- (IBAction)settingsButton:(id)sender {
    if(!self.settingsWindowController){
        self.settingsWindowController = [[SettingsWindowController alloc] initWithWindowNibName:@"SettingsWindow"];

        // It already has a property for the dbh, just give it to it
        self.settingsWindowController.dbh = self.dbh;
    }

    [self.settingsWindowController showWindow:self];
    self.settingsWindowController.delegate = self;
}

// And you don't need this, or the protocol
//-(dbHandler*)sendDBobject{
//    return dbh;
//}

为什么这样更好?有一个“告诉,不要问”的原则。在这种情况下,您是在告诉设置视图控制器 dbh 是什么,而不是让它询问其他对象。此外,您不再与符合协议的 App 委托耦合,这意味着控制器与您的应用程序中的其他对象的耦合较少。想象一下,你要对你的设置视图控制器进行单元测试,给它提供它想要的对象要容易得多,而不是为它设置基础设施来请求东西。

于 2013-06-25T13:14:56.623 回答
0

NSApp delegate您可以通过该方法从应用程序中的任何位置访问您的应用程序委托。因此,要获取dbh对象,您只需执行以下操作:

AppDelegate *appDelegate = [NSApp delegate];
dbh = appDelegate.dbh;
于 2013-06-24T21:23:08.293 回答