52

要するに、ビュー A とビュー B を切り替えることができる 2 つのフルスクリーン ビューが必要です。内部で何が起こっているのかを知るために、これがどのように手作業で行われるかを知りたいです。

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

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

@end

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

次に、ほとんど同じ方法で、別の 2 つのビュー コントローラーを作成しました。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;

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

更新: 私はそれをテストしました。ビュー コントローラ (例: ViewControllerA) を解放すると、viewDidDisappear にログ メッセージが表示されません。ViewControllerA を割り当てて初期化するときにのみ、viewDidLoad を取得します。しかし、それだけです。したがって、すべての兆候は現在、UITabBarController の巧妙さを表しています ;) そして、それを複製する方法を見つけなければなりませんよね?

4

4 に答える 4

50

Beginning iPhone Development の第 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];

}
于 2009-05-26T14:54:41.010 に答える
39

最も単純な 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];

于 2009-05-26T15:18:25.407 に答える
21

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

アプリケーション デリゲートに 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 です。

于 2009-05-26T14:40:36.403 に答える
2

これは古い問題かもしれませんが、最近同じ問題に遭遇し、うまくいくものを見つけるのに苦労しました. 私は 2 つの補完的なビュー コントローラーを切り替えたいと思っていましたが、切り替えをアニメーション化し (組み込みのアニメーションは正常に動作します)、可能であればストーリーボードと互換性を持たせたいと考えていました。

組み込みのトランジションを利用するために、UIView の+transitionFromView:toView:duration:options:completion:メソッドは美しく機能します。ただし、ビューコントローラーではなく、ビュー間でのみ遷移します。

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

参照実装についてはRAFlipReplaceSegue、このアプローチを使用してまとめた正確なカスタム セグエを参照してください。UINavigationControllerおまけとして、スタック内にある場合は、古いビュー コントローラーも新しいものに置き換えます。

于 2012-12-15T06:58:47.483 に答える