2013-02-26 6 views
6

Я искал много, много мест и еще не нашел хорошего примера кода, показывающего, как предварительно загрузить «следующую» страницу в UIPageViewController. Есть несколько ответов на SO, в которых подробно изложены некоторые теоретические способы сделать это (см. this question), но никто еще не опубликовал рабочий пример.Предварительная загрузка следующей страницы в UIPageViewController

В рабочем процессе моего приложения я показываю 1 страницу на экран, и я хочу, чтобы «следующий» экран был предварительно загружен, потому что, поскольку это так, прокрутка на следующую страницу может быть очень медленной, иногда требуется 2 щелчка (если вы прокручиваете слишком быстро), чтобы следующая страница была отображена и показана. Это обеспечивает плохой пользовательский интерфейс. Меня не волнует предварительная загрузка «предыдущих» или любых других экранов, поскольку типичный рабочий процесс будет состоять в том, что пользователи остаются на экране некоторое время, прежде чем переходить на следующий экран (справа). Я использую слайд-анимацию (не скручиваюсь). Я создаю все представления программно и не использую IB вообще.

Я пытался хранить некоторые UIViewControllers в NSMutableArray и загружать контроллеры оттуда, но сложно работать правильно и, похоже, ничего не ускоряет. Должен быть хороший способ сделать это.

Любая помощь очень ценится.

+1

Вы нашли решение для этого? У меня такая же проблема, и я вижу заметное отставание при прохождении к следующему контроллеру. – mattsson

+0

Сортировка, но ответ очень специфичен для моей реализации. Поскольку я много работал с UIPageViewController с момента публикации этого вопроса, я обнаружил, что это очень сложный вопрос. В основном, мои проблемы больше касались запросов к БД для получения правильных данных, что замедляло каждую страницу вниз. Я смог оптимизировать мои очереди страниц, предварительно вычисляя данные из БД и рисуя свои представления с помощью автоматической компоновки вместо того, чтобы возиться с фреймами - это очень помогло. Во-вторых, у меня было много изображений, чтобы показать, поэтому я сохранил их в NSMutableArray непосредственно на «основном» контроллере представлений (родительский салфетки). – DiscDev

+0

Мое «решение» закончилось тем, что ... продолжайте ждать, пока Apple выйдет с более быстрыми телефонами .... хахаха. На iPhone 6/6s больше нет отставания.Я оптимизировал некоторые из кода для извлечения базы данных, которые будут выполняться один раз, когда сначала будет создан контроллер страниц, и это очень помогло, но основные улучшения скорости были получены от более быстрых процессоров и большего количества оперативной памяти, а также поэтапная поддержка iPhone 4/4s =) – DiscDev

ответ

0

Вы должны отлаживать свой код, используя, например, Time Profiler of Instruments. Выполнение этого, вы обнаружите, какой объект имеет наибольшее время работы. Возможно, это не связано с UIPageViewController, но с представлением внутри страниц.

2

Я решил для своего дела в некоторой степени взломать. Для каждого ContentView у меня есть UIImageView в пределах UIScrollView для масштабирования. Моя проблема заключалась в том, что при загрузке приложения, если пользователь увеличил масштаб до прокрутки, переход на следующую страницу при увеличении не будет работать слишком хорошо. Для решения этой проблемы я использую следующий код (Swift 1.2). Как я уже сказал, это немного взломать.

var layoutsubs = false 

override func viewDidLoad() { 
    super.viewDidLoad() 
    //Other code for implementing pageViewController omitted 

    //add pageViewController to main view 
    self.addChildViewController(pageViewController) 
    self.view.addSubview(pageViewController.view) 
    pageViewController.didMoveToParentViewController(self) 

    //Load to the viewController after the starting VC, then go back to the starting VC 
    var viewControllers = [afterVC] 
    pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Forward, animated: true, completion: nil) 
    viewControllers = [startingVC] 
    pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Reverse, animated: true, completion: nil) 
} 

override func viewWillLayoutSubviews() { 
    //Load the viewController before the starting VC then go back to the starting VC 
    //viewWillLayoutSubviews() is called multiple times, so do this only once 
    if !layoutsubs { 
     let startingVC = self.viewControllerAtIndex(imageIndex) as ContentViewController 
     let beforeVC = pageViewController(pageViewController, viewControllerBeforeViewController: startingVC) as! ContentViewController 

     var viewControllers = [beforeVC] 
     pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Reverse, animated: true, completion: nil) 
     viewControllers = [startingVC] 
     pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Forward, animated: true, completion: nil) 
     layoutsubs = true 
    } 
} 

По существу, я загружаю контроллеры представлений до и после пускового контроллера. Я делаю это, устанавливая каждый из них в VC, чтобы увидеть через setViewControllers(_:direction:animated:completion:) (see ref), затем вернемся к стартовому контроллеру. Почему это происходит в двух разных функциях? Ну, если вы поместите все в один, загрузится только один из двух контроллеров представления рядом с стартовым VC. Это может быть желательно для некоторых случаев, но мне нужно было все три VC (до, начиная и после) для загрузки.

Я не уверен, насколько хорошо этот метод будет работать, если UIPageViewController уже загружен. Например, если вам нужно загрузить страницу 2 в сторону от просматриваемой страницы, после нескольких проверок. Он может пропустить, если вы положите его в willTransitionToViewControllers().

+0

Как это работает, если у вас нет фиксированного количества VC? Есть ли способ предварительно загрузить все из них сразу, чтобы не возникало проблем? Благодаря! – Jacob

+0

@Jacob: Если у вас нет фиксированного количества VC, вам сначала нужно будет проверить, есть ли VC до и после выбранного VC. Если после него есть только VC, вы будете использовать только код в 'viewDidLoad()', а 'viewWillLayoutSubviews()' не будет использоваться. Если перед ним есть только VC, вы будете использовать код в 'viewWillLayoutSubviews()', и все в 'viewWillLoad', начиная с комментария' // Load to viewController после запуска VC ... ', будет удалено. В этом случае вы можете перейти к предыдущему VC в 'viewDidLoad()'. Я не уверен, как предварительно загрузить все VC, извините. –

+0

привет, вы можете предоставить полный код от инициализации pageViewController, чтобы завершить его. –

Смежные вопросы