3

OSX 開発の最初のステップを設定していますが、いくつかの問題に遭遇しました。私は iOS 開発の経験がかなりありますが、OSX プログラムのウィンドウ システムは別のものです。

Twitter のようなソーシャル ネットワーク用のクライアントを作成しており、最初にアプリを起動するために 2 つの個別のウィンドウ コントローラーが必要です。 .plist に main.xib を指定する必要があります。このために、アプリの起動時に非表示にする空のxibを作成しました。これは実際には良い解決策ではありません IMO、これに対するより良い解決策は何ですか? 私は自分のコードを分離しておくことができるので、ウィンドウを appdelegate から分離したいと思っています。

ログインするために「2 番目の」ウィンドウを開くと、ウィンドウは表示されますが、アクティブではありません。orderFront:、activateIgnoringOtherApps:、makeKeyAndOrderFront: などのすべてを試しました。しかし、これはすべてうまくいきません..

そう: まず、info.plist で必要な main.xib を処理するより良い方法はありますか? そうでない場合、フォーカスの問題を回避する方法はありますか? 私はosx 10.7で作業しています

4

2 に答える 2

2

1回限りの場合は、アプリデリゲートをウィンドウコントローラーから分離する必要があります。先に進み、テンプレートから新しいCocoaアプリケーションを作成します。でMainMenu.xib、ウィンドウを削除します。AppDelegate.hを削除IBOutletNSWindowます。s(おそらくと)をNSWindowController含む完全ないくつかの新しいサブクラスを作成します。 XIBLoginWindowControllerTimelineWindowController

「最終的な」NSWindowControllerサブクラス(つまり、サブクラス化されないサブクラス)の場合、指定された初期化子のベストプラクティスは次のとおりです。

//for our example class LoginWindowController
- (id)init
{
    self = [super initWithWindowNibName:@"LoginWindowController"];
    if (self) {
        //....
    }
    return self;
}

これで、アプリデリゲートに@properties、2つの異なるウィンドウコントローラーインスタンスが必要になります。

//Within AppDelegate.m

#import "AppDelegate.h"
#import "LoginWindowController.h"
#import "TimelineWindowController.h"

@interface AppDelegate ()
@property (nonatomic) LoginWindowController *loginWindowController;
@property (nonatomic) TimelineWindowController *timelineWindowController;
//For the sake of this demo, add a property for the loggedIn state:
@property (nonatomic) BOOL loggedIn;
@end

アプリデリゲートには、正しいウィンドウコントローラーを提示する何らかのメソッドが必要です。それを呼びましょう-updateWindowVisibility

- (void)updateWindowVisibility
{
    BOOL isLoggedIn = self.loggedIn;

    BOOL loginWindowVisible = self.loginWindowController.window.isVisible;
    BOOL showLoginWindow = !isLoggedIn;

    BOOL timelineWindowVisible = self.timelineWindowController.window.isVisible;
    BOOL showTimelineWindow = isLoggedIn;

    if (!loginWindowVisible && showLoginWindow) {
        if (!self.loginWindowController) self.loginWindowController = [[LoginWindowController alloc] init];
        [self.loginWindowController showWindow:nil];
    } else if (loginWindowVisible && !showLoginWindow) {
        [self.loginWindowController close];
        self.loginWindowController = nil;
    }

    if (!timelineWindowVisible && showTimelineWindow) {
        if (!self.timelineWindowController) self.timelineWindowController = [[TimelineWindowController alloc] init];
        [self.timelineWindowController showWindow:nil];
    } else if (timelineWindowVisible && !showTimelineWindow) {
        [self.timelineWindowController close];
        self.timelineWindowController = nil;
    }
}

上記で実装されたこのメソッドは、現在のセットアップで必要とされるよりも少し多くの作業を実行しますが、他のウィンドウを表示/非表示にする必要がある場合は変更が簡単です。この時点であとは、から呼び出すだけ-updateWindowVisibilityです-applicationDidFinishLaunching:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    self.isLoggedIn = NO;
    [self updateWindowVisibility];
}

このアプローチを示すサンプルアプリをgithubに投稿しました。

于 2012-10-30T17:01:04.603 に答える
1

構造(あなたの最初の質問)に関して、私はこれをお勧めします:

  1. 1 つの空白のウィンドウと、それを覆う大きな NSView (たとえば、megaView と呼ばれる) を持つ XIB を作成します。大きな NSView の AppDelegate で IBOutlet を作成します。ロード時にこの XIB を使用するようにアプリを設定します。
  2. 2 つの別個の NSView XIB を作成します。1 つはログイン状態用、もう 1 つはログアウト状態用です。これらにレイアウトを入れます。
  3. 2 つの NSViewController サブクラスを作成します。1 つは、作成した各 NSView のロジックを制御します。それらをLoggedOutViewControllerおよびLoggedInViewControllerと呼びましょう。
  4. 作成した 2 つの NSView に戻ります。ログインした NSView のファイル所有者を LoggedInViewController に設定し、ログアウトした NSView のファイル所有者を LoggedOutViewController に設定します。各ファイル所有者のビュー (ファイル所有者を右クリックして検索) をそれぞれの NSView に接続します。
  5. アプリのデリゲートで、必要な方法でユーザーの認証ステータスを決定します。

ログインしている場合は、次のようにします。

NSViewController *loggedInController = [[NSViewController alloc] initWithNibName:@"NibNameGoesHere" bundle:nil];
[[self megaView] addSubview:[loggedInController view]];

それ以外の場合は、loggedOutController で上記のプロセスを実行します。

NSViewController *loggedOutController = [[NSViewController alloc] initWithNibName:@"OtherNibNameGoesHere" bundle:nil];
[[self megaView] addSubview:[loggedOutController view]];

これにより、必要なものが得られ、プロセスの2番目の質問が解決される可能性があります. 私の答えとネイトの答えの違いは、私の答えが同じウィンドウを使用していることです。ビュー コントローラーを条件付きでインスタンス化し、それらのビューをスーパービューに読み込むことは、おそらく私が学んだ Cocoa の最も重要な側面です。

于 2012-10-30T16:54:47.317 に答える