Подтвердить что ты не робот

Просмотр контроллеров: как программно переключаться между представлениями?

Вкратце: я хочу иметь два полноэкранных представления, где я могу переключаться между представлением A и представлением B. Я знаю, что могу просто использовать контроллер панели вкладок, но я этого не хочу. Я хочу посмотреть, как это делается вручную, чтобы узнать, что происходит под капотом.

У меня есть UIViewController, который действует как корневой контроллер:

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

@end

ContentView подключается к UIView, который я добавил в качестве представления в "представление" Nib. Это зеленый цвет, и я вижу его в полноэкранном режиме. Прекрасно работает.

Тогда я создал два других View Controllers почти так же. 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 при запуске приложения. Но теперь большой вопрос: A View Controller обычно имеет все такие методы, как:

  • (пустоты) viewWillAppear: (BOOL) анимационный;
  • (пустоты) viewDidDisappear: (BOOL) анимационный;
  • (пустоты) viewDidLoad;

... и так далее. Кто или что, или как будут вызваны эти методы, если я сделаю это "мой" путь без контроллера панели вкладок? Я имею в виду: если я выделил этот класс ViewController и вид стал видимым, мне нужно будет позаботиться о вызове этих методов? Как он знает, что viewWillAppear, viewDidDisappear или viewDidLoad? Я считаю, что у Tab Bar Controller есть все это "умение" под капотом. Или я не прав?

ОБНОВЛЕНИЕ: Я его протестировал. Если я отпущу контроллер вида (например: ViewControllerA), я не получу сообщения журнала в viewDidDisappear. Только при распределении и инициализации ViewControllerA я получаю viewDidLoad. Но это так. Итак, все признаки означают умность UITabBarController сейчас;) и мне нужно выяснить, как это сделать, правильно?

4b9b3361

Ответ 1

Вы можете начать с простейшего 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];

Ответ 2

Хороший пример переключения представлений в главе 6 "Начало разработки iPhone". Здесь вы можете увидеть исходный код: 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];

}

Ответ 3

Если я правильно понимаю, то, что вы пытаетесь сделать, довольно просто.

Просто добавьте UINavigationController в делегат вашего приложения и выполните:

[navigationController pushView:vcA];

Делегаты будут вызваны соответственно:

  • (пустоты) viewWillAppear: (BOOL) анимационный;
  • (пустоты) viewDidDisappear: (BOOL) анимационный;
  • (пустоты) viewDidLoad;

И когда вы хотите выставить представление и нажать еще один:

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

Если вы не хотите, чтобы навигационный контроллер показывал только использование:

[navigationBar setHidden:YES];

Если navigationBar - это UINavigationBar, соответствующий вашему UINavigationController.

Ответ 4

Это может быть старая проблема, но я недавно столкнулся с одной и той же проблемой и с трудом нашел что-то, что сработало. Я хотел переключиться между двумя дополнительными контроллерами представлений, но я хотел, чтобы коммутатор был анимированным (встроенный в анимацию работал отлично), и я хотел, чтобы он был совместим с раскадными версиями, если это возможно.

Для использования встроенного перехода метод UIView +transitionFromView:toView:duration:options:completion: работает красиво. Но это только переход между представлениями, а не просмотр контроллеров.

Для перехода между целыми контроллерами представления, а не только представлениями, создание пользовательского UIStoryboardSegue - это путь. Независимо от того, используете ли вы раскадровки, этот подход позволяет инкапсулировать весь переход и управлять передачей релевантной информации с одного контроллера представления на другой. Он включает только подклассификацию UIStoryboardSegue и переопределение одного метода, -perform.

Для ссылочной реализации см. RAFlipReplaceSegue, точный пользовательский сегмент, который я собрал, используя этот подход. В качестве бонуса он также заменяет старый контроллер представления новым, если он находится в стеке UINavigationController.