在UIViewControllers之间滚动而不会丢失最后一个状态

时间:2013-03-23 08:15:44

标签: ios xcode uiviewcontroller uinavigationcontroller

我有十个不同的UIViewControllers,每个right都包含leftpushController按钮。右箭头将使下一个控制器位于前面,而左侧控制器将带来前一个控制器。我需要在控制器之间导航而不会丢失最后一个状态。但每次按下右箭头,都会出现一个新的控制器。我尝试过presentController和{{1}}。我想在控制器之间自由导航而不会失去状态。你能指导一下怎么做吗?

2 个答案:

答案 0 :(得分:4)

这样的问题非常广泛,Cocoa Touch提供了许多管理视图控制器的机制。我建议阅读Apple的View Controller Programming Guide for iOS,特别是Presenting View Controllers from Other View ControllersCoordinating Efforts Between View Controllers部分。

话虽如此,这里有两种方法来管理多个UIViewControllers的流量,同时保持每个{@ 1}的活动状态,以便所有状态(UI和基础数据)在其使用期间持续存在。这两种方法的关键是主视图控制器协调所有需要呈现的UIViewControllers的切入和切换。

的UINavigationController

想象一下您的10个视图控制器1到10.如果用户始终首先呈现视图控制器编号1并且只能顺序地向前和向后导航,即用户无法直接在1到10之间导航,则此方法是合适的:

UINavigationController

A UINavigationController专门管理分层内容的导航。虽然我们可能不认为我们的10个视图控制器在概念上是分层的,但使用UINavigationController允许我们利用其现有功能进行顺序导航。在此模型中,每个视图控制器都可以保留对序列中以下视图控制器的引用,呈现它并实现其委托回调以了解何时将其解除:

UINavigationController

代码

  

MYPresentationViewController.h

@class MYPresentationViewController;


// The MYPresentationViewControllerDelegate allows the presenting view controller to know when the presented view controller (next highest in the presentation stack) has been dismissed.
@protocol MYPresentationViewControllerDelegate <NSObject>
- (void)viewControllerDidFinish:(MYPresentationViewController *)viewController;
@end


@interface MYPresentationViewController : UIViewController <MYPresentationViewControllerDelegate>

// The next view controller in the sequence.
@property (strong, nonatomic) MYPresentationViewController *nextViewController;

// The delegate responsible for showing and dismissing this view controller.
@property (assign) id<MYPresentationViewControllerDelegate> delegate;

@end
  

MYPresentationViewController.m

#import "MYPresentationViewController.h"

@implementation MYPresentationViewController

#pragma mark - Custom Property Assessors

// Returns the next view controller in the sequence. Creates and configures it if it doesn't already exist.
- (MYPresentationViewController *)nextViewController
{
    if (_nextViewController == nil)
    {
        _nextViewController = [[MYPresentationViewController alloc] initWithNibName:@"MYPresentationViewController" bundle:nil];
        _nextViewController.delegate = self;
    }
    return  _nextViewController;
}

#pragma mark - UI Control Event Handlers

- (IBAction)leftButtonPressed:(UIButton *)sender
{
    // Tell the delegate this view controller is ready to be dismissed.
    [self.delegate viewControllerDidFinish:self];
}

- (IBAction)rightButtonPressed:(UIButton *)sender
{
    // Present the next view controller.
    [self.navigationController pushViewController:self.nextViewController animated:YES];
}

#pragma mark - MYPresentationViewControllerDelegate

- (void)viewControllerDidFinish:(MYPresentationViewController *)viewController
{
    // Dismiss the next view controller to return to this one.
    [self.navigationController popViewControllerAnimated:YES];
}

@end

自定义主控制器

想象一下您的10个视图控制器1到10.如果可以向用户呈现不在任何一端(1或10)并且/或者用户可以在1到10之间导航的视图控制器,则此方法是合适的。直接允许循环导航:

Custom Master Controller

编写我们自己的“主控制器”,负责监督和设置需要呈现的所有UIViewControllers的切换和进出,这使我们能够以任何我们想要的方式实现导航。在此模型中,主视图控制器负责处理对所呈现的所有视图控制器的引用,呈现它们并实现其委托回调:

Custom Master Controller

代码

  

MYMasterViewController.h

#import "MYPresentationViewController.h"

@interface MYMasterViewController : UIViewController <MYPresentationViewControllerDelegate>

// The collection of view controllers to be presented.
@property (strong, nonatomic) NSArray *allViewControllers;

@end
  

MYMasterViewController.m

#import "MYMasterViewController.h"


@implementation MYMasterViewController

...

// Create 10 view controllers;
- (void)createViewControllers
{
    NSMutableArray *allViewControllers = [NSMutableArray arrayWithCapacity:10];

    // Create our 10 view controllers.
    for (int i = 0; i < 10; i++)
    {
        MYPresentationViewController *viewController = [[MYPresentationViewController alloc] initWithNibName:@"MYPresentationViewController" bundle:nil];
        viewController.delegate = self;
        viewController.index = i;
        [allViewControllers addObject:viewController];
    }

    self.allViewControllers = allViewControllers;
}

// Display first view controller, could be any in the sequence.
- (void)displayViewController
{
    MYPresentationViewController *firstViewController = [self.allViewControllers objectAtIndex:0];
    [self presentViewController:firstViewController animated:NO completion:nil];
}

#pragma mark - MYPresentationViewControllerDelegate

- (void)viewController:(MYPresentationViewController *)viewController didDismissWithButton:(kButtonPressed)button
{
    [self dismissViewControllerAnimated:NO completion:nil];

    // Determine the next view controller to display.
    NSInteger index = viewController.index;
    index += button == kButtonPressedLeft ? -1 : 1;
    if (index < 0) {
        index = self.allViewControllers.count - 1;
    }
    else if (index >= self.allViewControllers.count) {
        index = 0;
    }

    MYPresentationViewController *nextViewController = [self.allViewControllers objectAtIndex:index];
    [self presentViewController:nextViewController animated:NO completion:nil];
}

@end
  

MYPresentationViewController.h

@class MYPresentationViewController;


// Enumeration used to give a more descriptive code association with the presentation view controller's navigation button options.
typedef enum {
    kButtonPressedLeft,
    kButtonPressedRight,
} kButtonPressed;


// The MYPresentationViewControllerDelegate allows the presenting view controller to know when the presented view controller has been dismissed and with what button i.e. (left or right).
@protocol MYPresentationViewControllerDelegate <NSObject>
- (void)viewController:(MYPresentationViewController *)viewController didDismissWithButton:(kButtonPressed)button;
@end


@interface MYPresentationViewController : UIViewController

// The index of this view controller in relation to 10.
@property (assign) NSInteger index;

// The delegate responsible for showing and dismissing this view controller.
@property (assign) id<MYPresentationViewControllerDelegate> delegate;

@end
  

MYPresentationViewController.m

#import "MYPresentationViewController.h"

@implementation MYPresentationViewController

#pragma mark - UI Control Event Handlers

- (IBAction)leftButtonPressed:(UIButton *)sender
{
    // Tell the delegate this view controller is ready to be dismissed.
    [self.delegate viewController:self didDismissWithButton:kButtonPressedLeft];
}

- (IBAction)rightButtonPressed:(UIButton *)sender
{
    // Tell the delegate this view controller is ready to be dismissed.
    [self.delegate viewController:self didDismissWithButton:kButtonPressedRight];
}

@end

答案 1 :(得分:2)

您需要维护一堆视图控制器,类似于UINavigationController的工作。当您向右移动时,您只需获取阵列中的下一个视图控制器并显示它,而不是创建要显示的新视图控制器

然后为了维护状态,每个视图控制器应该负责管理自己的状态,并且因为在视图被移除然后再次呈现之后,每次状态都相同时,您不会创建新的控制器。

e.g。而不是

UIViewController *controller = //new view controller
[self presentViewController:controller];

你应该做

UIViewController *controller = [self.controllers nextViewController];
[self presentNextController:controller];