Я работаю над простым тестовым приложением, чтобы узнать все возможности 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];
}