我一直在开发一个简单的测试应用程序,以了解UIPageViewController的各个方面。我的应用程序可以正常工作,但我不确定我的执行方式是否最佳。希望你们中的一些人能指导我正确的方向。
为了获得基本的理解,我使用了这个教程作为起点。 http://www.appcoda.com/uipageviewcontroller-storyboard-tutorial/
该教程创建了一个应用程序,每个页面由UIPageViewController
呈现一个viewController
。然而,我需要利用UIPageViewController滚动浏览具有完全不同布局的页面。因此,为了进一步学习,我创建了一个主细节应用程序,在详细信息视图中使用UIPageViewController来显示三个不同的视图控制器。我仅为此测试应用程序显示图片和标签,但我当前正在构建的应用程序有三个视图控制器,其中每个控制器将包含一个表格视图、图像视图和文本视图,或一些文本字段。
这是我的测试应用程序的故事板。
我将DetailViewController
作为PageViewController
的数据源。在DVC的viewDidLoad
中,我以这种方式建立标签和图像,这些标签和图像将用于三个内容视图控制器firstViewController
、secondViewController
和thirdViewController
。
if ([[self.detailItem description] isEqualToString:@"F14's"]) {
//Here the page titles and images arrays are created
_pageTitles = @[@"Grim Reapers", @"Breakin the Barrier!", @"Top Gun"];
_pageImages = @[@"F14_Grim.jpg", @"F14boom.jpg", @"F14_topgun.jpg"];
//Here I call a method to instantiate the viewControllers
FirstController *selectedController = [self viewControllerAtIndex:0];
SecondController *nextController = [self viewControllerAtIndex:1];
ThirdController *lastController = [self viewControllerAtIndex:2];
[_vc addObject:selectedController];
[_vc addObject:nextController];
[_vc addObject:lastController];
_vc1 = @[selectedController];
} else if ([[self.detailItem description] isEqualToString:@"F35's"]){
//code is above is repeated
以下是实例化视图控制器的方法
- (UIViewController *)viewControllerAtIndex:(NSUInteger)index
{
if (([self.pageTitles count] == 0) || (index >= [self.pageTitles count])) {
return nil;
}
// Create a new view controller and pass suitable data.
if (index == 0) {
FirstController *fvc = [self.storyboard instantiateViewControllerWithIdentifier:@"FirstPageController"];
fvc.imageFile = self.pageImages[index];
fvc.titleText = self.pageTitles[index];
fvc.pageIndex = index;
if ([_vc count]) {
//Here I have to replace the viewController each time it is recreated
[_vc replaceObjectAtIndex:0 withObject:fvc];
}
return fvc;
} else if (index == 1) {
//Code is repeated for remaining viewControllers
viewDidLoad
中的代码是我感觉自己正在做不必要的工作的一个领域。我认为加载DVC时没有必要实例化所有三个视图控制器,但我不知道如何提供一个数组给UIPageViewControllerDataSource协议方法(viewControllerBeforeViewController
和viewControllerAfterViewController
)。
这是viewControllerBefore..
方法。
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger index = [_vc indexOfObject:viewController];
if ((index == 0) || (index == NSNotFound)) {
return nil;
}
index--;
//notice here I call my instantiation method again essentially duplicating work I have already done!
return [self viewControllerAtIndex:index];
}
总之,似乎我每次从一页滑到另一页时都不必要地重新创建视图控制器。这只是pageViewController的工作方式还是我过于复杂了。任何建议都将不胜感激!
解决方案
Matt提出了一个非常简单的解决方案,使用标识符。在我的Storyboard中,我只需勾选使用我已经实现的Storyboard标识符作为还原标识符的框。
然后在viewDidLoad
中,不再创建一个视图控制器数组,而是创建一个与还原标识符匹配的字符串数组。
if ([[self.detailItem description] isEqualToString:@"F14's"]) {
_pageTitles = @[@"Grim Reapers", @"Breakin the Barrier!", @"Top Gun"];
_pageImages = @[@"F14_Grim.jpg", @"F14boom.jpg", @"F14_topgun.jpg"];
FirstController *selectedController = [self viewControllerAtIndex:0];
[_vc addObject:@"FirstPageController"];
[_vc addObject:@"SecondPageController"];
[_vc addObject:@"ThirdPageController"];
_vc1 = @[selectedController];
最后,要确定代理方法中的索引,请执行以下操作而不是我之前所做的事情:
NSString * ident = viewController.restorationIdentifier;
NSUInteger index = [_vc indexOfObject:ident];
现在它可以在不必要地实例化视图控制器的情况下正常工作。
最后要注意的是,如果有人正在使用我在这里提供的内容,可以从viewControllerAtIndex:
方法中删除以下代码片段。
if ([_vc count]) {
//Here I have to replace the viewController each time it is recreated
[_vc replaceObjectAtIndex:0 withObject:fvc];
}