Я работаю над простым тестовым приложением, чтобы узнать все возможности UIPageViewController. У меня есть работа, но я не уверен, что мое исполнение - лучший способ. Надеюсь, некоторые из вас могут указать мне в правильном направлении.
Чтобы получить базовое понимание, я использовал этот учебник в качестве отправной точки. http://www.appcoda.com/uipageviewcontroller-storyboard-tutorial/
Учебник создает приложение, которое использует один viewController для каждой страницы, представленной UIPageViewController. Однако мне нужно использовать UIPageViewController для прокрутки страниц, которые имеют совершенно разные макеты. Поэтому, чтобы сделать учебное пособие еще одним шагом, я создал приложение мастера-детали, которое использует UIPageViewController в подробном представлении для отображения трех разных контроллеров представлений. Я застрял только с отображением изображений и меток для этого тестового приложения, но в приложении, которое я сейчас создаю, есть три диспетчера viewControllers, которые будут содержать либо tableview, imageView и textViews, либо некоторые текстовые поля.
Вот раскадровка для моего тестового приложения.

Я использую 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];
}