1つのアプローチは、NSBoxを使用することです。 このデモの完全なコードはgithubにあります。下部のリンクを参照してください。
入門
Cocoaアプリケーションテンプレートを使用して、Xcodeで新しいプロジェクトを開始します。適切なプレフィックスを使用してください。StackOverflowDemoにはSODを使用します。
他の作業を行う前に、テンプレートの一部としてプロジェクトに自動的に追加されたファイルにいくつかの小さな変更を加えます。
MainMenu.xib
:NSWindowを削除します。
- SODAppDelegate.h:次の行を削除します:
@property (assign) IBOutlet NSWindow *window;
例を単純化するために、左側にクリック可能なアイテム(簡単にするためにボタンなど)の列を持つ単一のウィンドウが必要だとします。
SODWindowController
NSWindowController
プロジェクトにサブクラスを追加することから始めます。対応するを必ず含めてくださいXIB
。開いSODWindowController.xib
て、ウィンドウの左側に4つのボタン(私は正方形のボタンを使用)を追加し、NSBox
ウィンドウの残りの部分を埋めて追加します。この時点で、あなたはこのようなものを少し持っているでしょう。
ボックスのcontentViewを、レイヤーの背景色が。のレイヤーホスティングビューに設定しました[NSColor greenColor]
。そうしないと、ボックスがまったく表示されないため、これを実行しました。ボックスは、ビューをスワップインおよびスワップアウトするためにのみ使用されるように構成されています。このようにボックスを構成するには、Interface Builderでとを選択NSBox
し、属性インスペクターでをに設定し、Title Position
をにNone
設定Border Type
しますNone
。
今、SODWindowController.m
で、スタブを交換してくださいinitWithWindow:
- (id)initWithWindow:(NSWindow *)window
{
self = [super initWithWindow:window];
if (self) {
// Initialization code here.
}
return self;
}
別の指定された初期化子を使用:
- (id)init
{
self = [super initWithWindowNibName:@"SODWindowController"];
{
}
return self;
}
これにより、再入力(および潜在的にXIBの名前の入力ミス)を回避できます。
SODWindowController
さらに、行の直後にクラス拡張子を追加します
#import "SODWindowController.h"
で、自分自身に:SODWindowController.m
を与えますIBOutlet
NSBox
@interface SODWindowController ()
@property (nonatomic, strong, readwrite) IBOutlet NSBox *box;
@end
Interface BuilderでSODWindowController.xib
、ボックスアウトレットを開き、追加したものを指すように設定しますNSBox
。
SODWindowControllerをSODAppDelegateに追加します
ここで、を追加しSODWindowController
ます:すぐ下SODAppDelegate
に行を追加します:SODAppDelegate.m
#import "SODAppDelegate.h"
#import "SODWindowController.h"
@interface SODAppDelegate ()
@property (nonatomic, strong, readwrite) SODWindowController *windowController;
@end
これで、ウィンドウを次の場所に作成するように設定できます-[NSApplication applicationDidFinishLaunching:]
。
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
self.windowController = [[SODWindowController alloc] init];
//notice that we don't have to do anything awkward like use initWithWindowNibName:
[self.windowController showWindow:nil];
}
この時点で、アプリを実行すると、ウィンドウが表示されます。
すばらしいですが、ユーザーが戻ることができるように、4つの異なるボタンの異なるビューと履歴についてはどうでしょうか。
SODViewControllers
4つのビューのそれぞれについて、NSViewControllerサブクラスを作成します。私SODCoffeeViewController
の名前をSODTeaViewController
、、、SODJavaViewController
と呼びますSODMeViewController
。
それぞれで、自動生成された指定された初期化スタブを置き換えます
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Initialization code here.
}
return self;
}
と
- (id)init
{
self = [super initWithNibName:@"SODCoffeeViewController" bundle:nil];
if (self) {
}
return self;
}
もちろん、それぞれに適切なNibName引数を代入します。以前と同様に、これにより、そのペン先に関連付けられているファイルの外部に「@"MyNibName」と入力する必要がなくなります。
SODViewControllersをSODWindowControllerに追加します
次に、4つすべてのView ControllerをにインポートしますSODWindowController
:行を追加します
#import "SODCoffeeViewController.m"
#import "SODTeaViewController.m"
#import "SODJavaViewController.m"
#import "SODTeaViewController.m"
これらSODWindowController
の各オブジェクトの1つが必要です。クラス拡張NSArray
にプロパティを追加する最も簡単な方法SODWindowController
@property (nonatomic, strong, readwrite) NSArray *viewControllers;
-[SODWindowController init]
と行を追加の実装で
- (id)init
{
self = [super initWithWindowNibName:@"SODWindowController"];
if (self) {
NSMutableArray *mutableViewControllers = [NSMutableArray array];
[mutableViewControllers addObject:[[SODCoffeeViewController alloc] init]];
[mutableViewControllers addObject:[[SODTeaViewController alloc] init]];
[mutableViewControllers addObject:[[SODJavaViewController alloc] init]];
[mutableViewControllers addObject:[[SODMeViewController alloc] init]];
self.viewControllers = [mutableViewControllers copy];
}
return self;
}
これで、表示する4つのビューごとに1つのビューコントローラーがあり、ウィンドウにある4つのボタンと同じように配列で並べられています。さらに重要なのは、4つのボタンのタグと同じように並べられていることです。...タグを設定した後、つまり。
SODWindowController.xib
Interface Builderで開き、一番上のボタンのタグを、上から2番目のボタンなどに設定し0
ます1
。
戻って、クラス拡張子SODWindowController.m
にを追加します。IBAction
SODWindowController
- (IBAction)showPane:(id)sender;
このメソッドを次のように定義SODWindowController
@implemention
します。
- (void)showPane:(NSButton *)sender
{
[self showPaneAtIndex:sender.tag];
}
以上です!
...もちろん定義する場合を除き-[SODWindowController showPaneAtIndex:]
ます。ただし、その前に、の4つのボタンのアクションをオンに設定SODWindowController.xib
しshowPane:
てFile's Owner
ください。
それが完了したら、次のように定義showPaneAtIndex:
します。
- (void)showPaneAtIndex:(NSInteger)index
{
NSViewController *viewController = (NSViewController *)self.viewController[(NSUInteger)index];
[self.box setContentView:viewController.view];
}
これで、いずれかのボタンが押されるたびに、対応するViewControllerのビューがボックスのコンテンツビューとして設定されます。
おそらく、ウィンドウが表示されたらすぐに、最上位のView Controllerのビュー(SODCoffeeViewController
's)を表示する必要があります。これを実現するには、の現在の定義を次のように置き換えます-windowDidLoad
。
- (void)windowDidLoad
{
[super windowDidLoad];
[self showPaneAtIndex:0];
}
歴史
歴史は実際には最も簡単な部分です。私たちが行うことは、私たちの後ろにある(ブラウザの戻るボタンの意味で)1つまたは2つのペインと、私たちの前にある(進むボタンの意味で)ペインの配列を追跡することです。これを行うには、2つの可変配列プロパティをSODWindowController
クラス拡張に追加します。
@property (nonatomic, strong, readwrite) NSMutableArray *panesBehind;
@property (nonatomic, strong, readwrite) NSMutableArray *panesBefore;
でそれらを初期化します-init
:
...
self.viewControllers = [mutableViewControllers copy];
self.panesBehind = [NSMutableArray array];
self.panesBefore = [NSMutableArray array];
}
return self;
}
次に、アクセスする新しい各ペインのインデックスをプッシュする必要があるself.panesBehind
ので、行を追加します
[self.panesBehind addObject:[NSNumber numberWithInteger:index]];
の定義に-showPaneAtIndex:
。
-goBack
これにより、-goForward
とヘルパー-canGoBack
を-canGoForward
次のように定義できます。
- (BOOL)canGoBack
{
return self.panesBehind.count > 0;
}
- (void)goBack
{
if (self.canGoBack) {
NSNumber *presentPane = self.panesBehind.lastObject;
[self.panesBehind removeLastObject];
[self.panesBefore insertObject:presentPane atIndex:0];
NSNumber *previousPane = self.panesBehind.lastObject;
[self.panesBehind removeLastObject];
[self showPaneAtIndex:previousPane.integerValue];
}
}
- (BOOL)canGoForward
{
return self.panesBefore.count > 0;
}
- (void)goForward
{
if (self.canGoForward) {
NSNumber *nextPane = [self.panesBefore objectAtIndex:0];
[self.panesBefore removeObjectAtIndex:0];
[self showPaneAtIndex:nextPane.integerValue];
}
}
ただし、これには小さな問題があります。ペインAからB、C、Dに進むと、self.panesBehind
次のようになります。
A-->B-->C-->D
そしてself.panesBefore
空です。しかし、2つのペインに戻ると、self.panesBehind
次のようになります。
A-->B
のようにself.panesBefore
見えます
C-->D
この時点でペインEに移動すると、次のself.panesBehind
ようになります。
A-->B-->E
予想どおりですが、self.panesBefore
それでも次のようになります
C-->D
これは私たちが望んでいることではありません。このため、行を追加します
[self.panesBefore removeAllObjects];
の終わりまで-showPane:
。
これらのメソッドを試すには、先に進んで、ので公に宣言し@interface
てSODWindowController
くださいSODWindowController.h
。
@interface SODWindowController : NSWindowController
- (void)goForward;
- (void)goBack;
@end
次に、とMainMenu.xib
のファイルメニューに2つのメニュー項目を追加します。2つ宣言する:Forward
Back
SODAppDelegate.h
IBActions
- (IBAction)forward:(id)sender;
- (IBAction)back:(id)sender;
に戻ってMainMenu.xib
、[進む]メニュー項目のアクションをに設定し、forward:
[First Responder
戻る]メニュー項目のアクションをに設定back:
しますFirst Responder
。最後に、2つのメソッドを定義-[SODAppDelegate forward:]
し、次-[SODAppDelegate back:]
の対応するメソッドを呼び出しますSODWindowController
。
- (IBAction)forward:(id)sender
{
[self.windowController goForward];
}
- (IBAction)back:(id)sender
{
[self.windowController goBack];
}
完全なソースをダウンロードするには、https://github.com/natechan/ViewSwappingDemoにアクセスしてください。