Как реализовать UIPageViewController, который использует несколько ViewController
Я работал над простым тестовым приложением, чтобы изучить все тонкости UIPageViewController. У меня это работает, но я не уверен, что мое исполнение - лучший способ. Я надеюсь, что некоторые из вас могут указать мне правильное направление.
Чтобы получить базовое понимание, я использовал этот учебник в качестве отправной точки.http://www.appcoda.com/uipageviewcontroller-storyboard-tutorial/
Учебник создает приложение, которое использует одинviewController
для каждой из страниц, представленныхUIPageViewController
, Однако мне нужно использовать UIPageViewController для прокрутки страниц, которые имеют совершенно разные макеты. Поэтому, чтобы продвинуть учебник дальше, я создал приложение master-detail, которое использует UIPageViewController в подробном представлении для отображения трех различных контроллеров представления. Я придерживался только отображения изображений и меток для этого тестового приложения, но приложение, которое я сейчас создаю, имеет три viewController, которые будут содержать либо tableview, imageView и textViews, либо некоторые textFields.
Вот раскадровка для моего тестового приложения.
Я используюDetailViewController
в качестве источника данных дляPageViewController
, ВviewDidLoad
из DVC я устанавливаю метки и изображения, которые будут использоваться в трех контроллерах представления контента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, или я слишком усложнил процесс. Любой вклад был бы великолепен!
РЕШЕНИЕ
Мэтт предложил невероятно простое решение в использованииидентификаторы, В моей раскадровке я просто установил флажок, который использует мой уже реализованный идентификатор раскадровки в качестве идентификатора восстановления
Затем вviewDidLoad
вместо создания массива viewControllers, просто создайте массив строк, которые соответствуют идентификаторам восстановления.
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];
}