web-dev-qa-db-ja.com

View Controller:プログラムでビューを切り替える方法は?

要するに、ビューAとビューBを切り替えることができる2つのフルスクリーンビューが必要です。TabBar Controllerを使用できることは知っていますが、したくありません。フードの下で何が起こっているかを知るために、これが手作業でどのように行われるかを知りたい.

ルートコントローラーとして機能するUIViewControllerがあります。

@interface MyRootController : UIViewController {
    IBOutlet UIView *contentView;
}
@property(nonatomic, retain) UIView *contentView;

@end

ContentViewは、サブビューとしてNibの「ビュー」に追加したUIViewに接続されています。これは緑色で、フルスクリーンで表示されます。正常に動作します。

次に、他の2つのView Controllerをほぼ同じ方法で作成しました。 ViewControllerAおよびViewControllerB。 ViewControllerAの背景は青、ViewControllerBの背景は黒です。どれがアクティブかを確認するだけです。

したがって、myRootControllerの実装では、次のようにします。

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

    ViewControllerA *vcA = [[ViewControllerA alloc] initWithNib];
    [self.contentView addSubview:vcA.view];

    [cvA release];
}

ところで、-initWithNibメソッドは次のようになります。

- (id)initWithNib { // Load the view nib
    if (self = [super initWithNibName:@"ViewA" bundle:nil]) {
        // do ivar initialization here, if needed
    }
    return self;
}

動作します。アプリを起動すると、ViewControllerAからビューが表示されます。しかし、大きな問題は次のとおりです。通常、View Controllerには次のようなすべてのメソッドがあります。

  • (void)viewWillAppear:(BOOL)アニメーション;
  • (void)viewDidDisappear:(BOOL)アニメーション;
  • (void)viewDidLoad;

...等々。 Tab Bar Controllerなしで「自分の」方法で実行した場合、これらのメソッドは誰または何、またはどのように呼び出されますか?つまり、ViewControllerのクラスを割り当て、ビューが表示される場合、これらのメソッドの呼び出しに注意する必要がありますか? viewWillAppear、viewDidDisappear、またはviewDidLoadをどのように知るのですか? Tab Bar Controllerには、この「賢さ」がすべて隠されていると思います。それとも私は間違っていますか?

更新:私はそれをテストしました。 View Controller(たとえば、ViewControllerA)をリリースすると、viewDidDisappearでログメッセージが表示されません。 ViewControllerAを割り当てて初期化するときにのみ、viewDidLoadを取得します。しかし、それだけです。つまり、すべての兆候はUITabBarControllerの巧妙さを表しています;)そして、私はそれを複製する方法を理解する必要がありますよね?

52
Thanks

最も単純なremoveFromSuperview/insertSubviewから始めて、少しずつコードを追加できます。


//SwitchViewController.h
#import 
@class BlueViewController;
@class YellowViewController;

@interface SwitchViewController : UIViewController {
    IBOutlet BlueViewController *blueViewController;
    IBOutlet YellowViewController *yellowViewController;
}
- (IBAction)switchViews:(id)sender;
@property (nonatomic, retain) BlueViewController *blueViewController;
@property (nonatomic, retain) YellowViewController *yellowViewController;
@end

//1. remove yellow view and insert blue view
- (IBAction)switchViews:(id)sender {
    if(self.blueViewController.view.superview == nil)
    {
        [yellowViewController.view removeFromSuperview];
        [self.view insertSubview:blueViewController.view atIndex:0];
    }
}

//2. appear=insert, disappear=remove
if(blueViewController.view.superview == nil)
{
    [blueViewController viewWillAppear:YES];
    [yellowViewController viewWillDisappear:YES];

    [yellowViewController.view removeFromSuperview];
    [self.view insertSubview:self.blueViewController.view atIndex:0];

    [yellowViewController viewDidDisappear:YES];
    [blueViewController viewDidAppear:YES];
}

//3. now add animation
[UIView beginAnimations:@"View Flip" context:nil];
[UIView setAnimationDuration:1.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
//blue view will appear by flipping from right
if(blueViewController.view.superview == nil)
{
    [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight 
                            forView:self.view cache:YES];

    [blueViewController viewWillAppear:YES];
    [yellowViewController viewWillDisappear:YES];

    [yellowViewController.view removeFromSuperview];
    [self.view insertSubview:self.blueViewController.view atIndex:0];

    [yellowViewController viewDidDisappear:YES];
    [blueViewController viewDidAppear:YES];
}
[UIView commitAnimations];

39
Chilly Zhong

IPhone開発の開始の第6章に、ビューを切り替える素敵な例があります。ソースコードはここで見ることができます: http://iphonedevbook.com/

SwitchViewControllerには、プログラムでビューを変更するコードがあります。


- (IBAction)switchViews:(id)sender
{

    if (self.yellowViewController == nil)
    {
        YellowViewController *yellowController = [[YellowViewController alloc]
                initWithNibName:@"YellowView" bundle:nil];
        self.yellowViewController = yellowController;
        [yellowController release];
    }

    [UIView beginAnimations:@"View Flip" context:nil];
    [UIView setAnimationDuration:1.25];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

    UIViewController *coming = nil;
    UIViewController *going = nil;
    UIViewAnimationTransition transition;

    if (self.blueViewController.view.superview == nil) 
    {   
        coming = blueViewController;
        going = yellowViewController;
        transition = UIViewAnimationTransitionFlipFromLeft;
    }
    else
    {
        coming = yellowViewController;
        going = blueViewController;
        transition = UIViewAnimationTransitionFlipFromRight;
    }

    [UIView setAnimationTransition: transition forView:self.view cache:YES];
    [coming viewWillAppear:YES];
    [going viewWillDisappear:YES];
    [going.view removeFromSuperview];
    [self.view insertSubview: coming.view atIndex:0];
    [going viewDidDisappear:YES];
    [coming viewDidAppear:YES];

    [UIView commitAnimations];

}
50
nevan king

私が正しく理解していれば、あなたが達成しようとしていることは非常に簡単です。

アプリケーションデリゲートにUINavigationControllerを追加して、次の操作を行います。

[navigationController pushView:vcA];

デリゲートはそれに応じて呼び出されます。

  • (void)viewWillAppear:(BOOL)アニメーション;
  • (void)viewDidDisappear:(BOOL)アニメーション;
  • (void)viewDidLoad;

そして、ビューをポップして別のビューをプッシュしたい場合:

[navigationController popViewControllerAnimated:true];
[navigationController pushView:vcB];

NavigationControllerの表示のみを使用したくない場合:

[navigationBar setHidden:YES];

NavigationBarは、UINavigationControllerに対応するUINavigationBarです。

21

これは古い問題かもしれませんが、最近同じ問題に遭遇し、機能するものを見つけるのに苦労しました。 2つの補完的なView Controllerを切り替えたいと思っていましたが、スイッチをアニメーション化して(アニメーションがうまく動作するように)、できればストーリーボードと互換性を持たせたいと思いました。

組み込みのトランジションを利用するために、UIViewの +transitionFromView:toView:duration:options:completion: メソッドは美しく機能します。しかし、それはビュー間の遷移のみであり、View Controllerではありません。

ビューだけでなくView Controller全体に移行するには、カスタムのUIStoryboardSegueを作成する方法があります。ストーリーボードを使用するかどうかにかかわらず、このアプローチにより、移行全体をカプセル化し、1つのビューコントローラーから次のビューコントローラーへの関連情報の受け渡しを管理できます。 UIStoryboardSegueをサブクラス化し、単一のメソッド-performをオーバーライドするだけです。

リファレンス実装については、 RAFlipReplaceSegue を参照してください。このアプローチを使用して作成した正確なカスタムセグエです。ボーナスとして、古いView ControllerがUINavigationControllerスタックにある場合、新しいView Controllerに置き換えられます。

2
Ryan Artecona