-1

OS X 用のアプリを開発していますが、問題が発生しました。

アプリの構造は次のとおりです。

  • AppDelegate: MainMenu.xib からの主なアクションが実行される場所。また、メイン ウィンドウが作成される場所でもあります。

  • SettingsWindowController: 設定ウィンドウは、SettingsWindow.xib からのインターフェイスで定義されます。

  • これら 2 つのクラスを委任するプロトコル SettingsWindowProtocol を作成しました。

  • AppDelegate で obj として初期化されるもう 1 つのクラス dbHandler を作成dbhしました。

  • SettingsWindowProtocol でオブジェクトを送信するメソッドを作成しましたが、SettingsWindowControl でこのメソッドを呼び出した後、オブジェクトは null です。

問題は、2 つの異なるクラスで同じオブジェクトを共有する方法です。

質問に関連するコードのいくつかのブロック:

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;
}

SettingsWindowController.h :

#import "dbHandler.h"

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

@interface SettingsWindowController : NSWindowController

@property (assign) id<SettingsWindowControllerProtocol> delegate;

@property (retain) dbHandler* dbh;

@end

SettingsWindowController.m:

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

2 に答える 2

1

アプリケーションで不適切な設計を選択したようです。dbh を取得するためにアプリ デリゲートを呼び出しているだけでなく、アクション メッセージ ( settingsButton:) に応答するメソッドもそこにあるようです。一般に、アプリ デリゲートはアプリケーションのデリゲートとして存在し、デリゲート メソッドに応答します。それ以上のことをするのは、経験の浅い開発者の兆候です。新しい開発者がアプリ デリゲートを便利なシングルトン オブジェクトとして使用しているのをよく見かけます。オブジェクト指向の方法ではなく、データやメソッドを隠しておくことができます。

Xcode アプリケーション テンプレートが AppDelegate のコア データ スタックを初期化することは役に立ちません。また、多くのチュートリアルではデリゲートをストレージとして使用します。これは、本来のやり方で複雑さを増すのではなく、プロジェクトをチュートリアルの主題に集中させ続けるためです。現実世界で行われます。

デリゲートにはできる限り少ないことをしてもらいたいということを覚えておいてください。そのため、アプリケーション デリゲートに最小限の数のオブジェクトをセットアップさせ、それらをまとめて邪魔にならないようにします。

あなたの場合、あなたがもっとうまくやれることが2つあります。アプリのデリゲートを呼び出してオブジェクトを取得するプロトコルを設定するのではなく、スタックからビュー コントローラーに送信するだけです。次に、アプリケーション デリゲートにアクション メソッドがあり、代わりにビュー コントローラーの方が適しています。私は2番目にあまり深く入りたくないので、あなたの質問はオブジェクトの共有に関するものです。プロトコルを使用せずにオブジェクトをスタックに渡す方法を次に示します。

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;
//}

なぜこれが良いのですか?「聞くな、聞くな」の原則があります。この場合、設定View Controllerに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 に答える