我有十个不同UIViewControllers
的,每个都包含一个right
和left
按钮。右箭头会将下一个控制器带到前面,而左箭头会将前一个控制器带到前面。我需要在控制器之间导航而不会丢失最后一个状态。但是每次按下右箭头时,都会出现一个新的控制器。我试过pushController
和presentController
. 我想在控制器之间自由导航而不会丢失状态。能指导下怎么做吗?
2 回答
像这样的问题非常广泛,Cocoa Touch提供了许多管理视图控制器的机制。我建议阅读 Apple 的iOS 视图控制器编程指南,特别是从其他视图控制器呈现视图控制器和视图控制器之间的协调工作部分。
话虽如此,这里有两种方法可以管理多个数据流,UIViewControllers
同时让每个数据流保持活动状态,以便它们的所有状态(UI 和底层数据)在使用期间保持不变。这两种方法的关键是主视图控制器协调所有UIViewControllers
需要呈现的内容的切换。
UINavigationController
想象一下您的 10 个视图控制器 1 到 10。如果用户总是首先呈现视图控制器编号 1 并且只能通过它们顺序向前和向后导航,即用户不能直接在 1 和 10 之间导航,则这种方法是合适的:
AUINavigationController
专门管理分层内容的导航。尽管我们可能不认为我们的 10 个视图控制器在概念上是分层的,但使用 aUINavigationController
允许我们利用其现有功能进行顺序导航。在这个模型中,每个视图控制器都负责保持对序列中以下视图控制器的引用,呈现它并实现它的委托回调以知道何时关闭它:
代码
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 之间导航,则这种方法是合适的循环导航:
编写我们自己的“主控制器”来监督和促进所有UIViewControllers
需要呈现的内容的切换,使我们能够以任何我们想要的方式实现导航。在这个模型中,主视图控制器负责处理对所有正在呈现的视图控制器的引用,呈现它们并实现它们的委托回调:
代码
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
你需要维护一堆视图控制器,类似于 UINavigationController 所做的。当您向右移动时,无需创建新的视图控制器来呈现,您只需获取数组中的下一个视图控制器并呈现它
然后为了维护状态,每个视图控制器都应该负责管理自己的状态,并且由于您不是每次都创建新控制器,因此在视图被删除然后再次呈现后状态将是相同的。
例如,而不是
UIViewController *controller = //new view controller
[self presentViewController:controller];
你应该做
UIViewController *controller = [self.controllers nextViewController];
[self presentNextController:controller];