【发布时间】:2014-03-05 16:03:30
【问题描述】:
我一直在开发一个简单的测试应用程序来了解 UIPageViewController 的来龙去脉。我有它的工作,但我不相信我的执行是最好的方式。我希望你们中的一些人能指出我正确的方向。
为了获得基本的理解,我以本教程为起点。 http://www.appcoda.com/uipageviewcontroller-storyboard-tutorial/
本教程创建一个应用程序,该应用程序为UIPageViewController 提供的每个页面使用一个viewController。但是,我需要利用 UIPageViewController 滚动浏览具有完全不同布局的页面。因此,为了进一步学习本教程,我创建了一个主从应用程序,它在详细视图中使用 UIPageViewController 来显示三个不同的视图控制器。我坚持只为这个测试应用程序显示图像和标签,但我目前正在构建的应用程序有三个 viewControllers,它们将包含一个 tableview、imageView 和 textViews,或者一些 textFields。
这是我的测试应用的故事板。
我使用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
下面是实例化viewControllers的方法
- (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 在使用 标识符 时提出了一个非常简单的解决方案。在我的故事板中,我只是选中了使用我已经实现的故事板标识符作为恢复标识符的框
然后在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: 方法中删除以下 sn-p。
if ([_vc count]) {
//Here I have to replace the viewController each time it is recreated
[_vc replaceObjectAtIndex:0 withObject:fvc];
}
【问题讨论】:
-
你能上传一些关于这个的示例代码吗?谢谢!
-
@fguespe 您应该在这里拥有解决此问题所需的一切...不确定您还在寻找什么...请注意我在问题的底部添加了一个解决方案
-
这是一个很棒的解决方案。但是我无法获得正确的页面索引以用于其他功能。您是将 NSString * ident 等放在根控制器中还是在模型的 - (NSUInteger)indexOfViewController:(embBaseViewController *)viewController 中?
-
@malaki1974
NSString *ident行位于viewControllerBeforeViewController:和viewControllerAfterViewController:委托方法中的根控制器中……。我不确定您要实现什么,但您说您正在尝试获取页面索引以用于其他功能。您也许可以为控制器创建一个currentPageIndex属性,这样您就可以在其他函数中始终调用self.currentPageIndex之类的东西……希望对您有所帮助 -
嗨@Ben,尽管代码对许多人来说是相当不言自明的,但看到一个工作示例会有很大帮助。你能把你的代码发布到 github 上吗?
标签: ios uiviewcontroller uipageviewcontroller