2013-02-26 12 views
6

Sprawdziłem wiele, wiele miejsc i jeszcze nie znalazłem dobrego kodu przykładowego pokazującego, jak wstępnie załadować "następną" stronę w UIPageViewController. Jest kilka odpowiedzi na SO opisujących kilka teoretycznych sposobów na to (patrz this question), ale nikt jeszcze nie opublikował działającego przykładu.Wstępnie załaduj następną stronę w UIPageViewController

W przepływie pracy z mojej aplikacji wyświetlam 1 stronę na ekranie i chcę mieć wstępnie załadowany ekran "następny", ponieważ tak jest, przesuwanie do następnej strony może być bardzo powolne, czasami wymagające 2 przeciągnięć (jeśli przesuwasz zbyt szybko), aby następna strona była wyświetlana i pokazywana. Zapewnia to złe wrażenia użytkownika. Naprawdę nie obchodzi mnie wstępne ładowanie "poprzednich" lub innych ekranów, ponieważ typowy przepływ pracy polega na tym, że użytkownicy pozostają na ekranie przez chwilę, zanim przejdą do następnego ekranu (po prawej). Używam animacji slajdów (nie zwijam się). Tworzę wszystkie widoki programowo i wcale nie używam IB.

Próbowałem przechowywać niektóre UIViewControllers w NSMutableArray i załadować kontrolerów stamtąd, ale jest to trudne do prawidłowego działania i nie wydaje się, aby przyspieszyć cokolwiek. Musi być na to dobry sposób.

Każda pomoc jest bardzo doceniana.

+1

Czy znalazłeś rozwiązanie problemu? Mam ten sam problem, zauważalne opóźnienie podczas przesuwania do następnego kontrolera widoku. – mattsson

+0

Sortuj, ale odpowiedź jest bardzo specyficzna dla mojej implementacji. Ponieważ bardzo dużo pracowałem z UIPageViewController od opublikowania tego pytania, odkryłem, że jest to bardzo trudny temat. Zasadniczo moje problemy miały więcej wspólnego z wysyłaniem zapytań do DB, aby wyświetlić odpowiednie dane, co spowalniało każdą stronę. Byłem w stanie zoptymalizować zwroty stron poprzez wstępne obliczenie danych z bazy danych, a rysowanie widoków za pomocą funkcji automatycznego układu zamiast manipulowania ramkami - to bardzo pomogło. Po drugie miałem dużo obrazów do pokazania, więc zapisałem je w NSMutableArray bezpośrednio na "głównym" kontrolerze widoku (rodzic machnięcia). – DiscDev

+0

Moje "rozwiązanie" zakończyło się tym, że ... czekam, aż Apple wyjdzie z szybszymi telefonami .... hahaha. Na iPhone'ach 6/6s nie ma już opóźnień.Zoptymalizowałem część kodu pobierania bazy danych, aby zdarzyło się raz, gdy najpierw utworzono kontroler stron i to bardzo pomogło, ale główna poprawa szybkości pochodzi od szybszych procesorów i większej ilości pamięci RAM, a także od zerwania obsługi iPhone'a 4/4s =) – DiscDev

Odpowiedz

0

Będziesz debugował swój kod, używając, na przykład Profilera czasu instrumentów. W ten sposób dowiesz się, który obiekt ma najwyższy czas działania. Może to nie jest powiązane z UIPageViewController, ale z widokiem na stronach.

2

Rozwiązałem dla mojej sprawy trochę hackowania. Dla każdego ContentView, mam UIImageView w obrębie UIScrollView dla powiększania. Mój problem polegał na tym, że po uruchomieniu aplikacji, jeśli użytkownik był powiększany przed przesuwaniem, przejście do następnej strony podczas powiększania nie działałoby zbyt dobrze. Używam następującego kodu (Swift 1.2), aby rozwiązać ten problem. Jak już powiedziałem, jest to trochę hack.

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 
    } 
} 

Przede wszystkim ładuję kontrolery widoku przed uruchomieniem kontrolera widoku i za nim. Robię to, ustawiając każdy z nich na VC, aby zobaczyć przez setViewControllers(_:direction:animated:completion:) (see ref), a następnie powracając do kontrolera widoku początkowego. Dlaczego jest to w dwóch różnych funkcjach? Cóż, jeśli umieścisz wszystko w jednym, załaduje się tylko jeden z dwóch kontrolerów widoku obok początkowego VC. Może to być pożądane w niektórych przypadkach, ale potrzebowałem wszystkich trzech VC (przed, na początku i po) do załadowania.

Nie jestem pewien, jak dobrze ta metoda zadziała, jeśli UIPageViewController był już załadowany. Na przykład, jeśli musisz wczytać stronę 2 z wyświetlanej strony, po kilku przeskokach. Może pominąć, jeśli umieścisz go w willTransitionToViewControllers().

+0

Jak to działa, jeśli nie masz ustalonej kwoty VC? Czy istnieje sposób wstępnego wczytania wszystkich naraz, więc nie ma problemów? Dzięki! – Jacob

+0

@Jacob: Jeśli nie masz ustalonej ilości VC, musisz najpierw sprawdzić, czy istnieją VC przed i po wybranym VC. Jeśli po nim jest tylko VC, użyjesz go tylko w 'viewDidLoad()', a 'viewWillLayoutSubviews()' nie będzie użyty. Jeśli przed nim jest tylko VC, użyjesz go w 'viewWillLayoutSubviews()', a wszystko w 'viewWillLoad' zaczyna się od' // Wczytaj do kontrolera view po uruchomieniu VC ... 'komentarz zostanie usunięty. Możesz w tym przypadku przejść do poprzedniego VC w 'viewDidLoad()'. Nie jestem pewien, jak załadować wszystkie VC, przepraszam. –

+0

hello Czy możesz podać pełny kod z inicjowania pageViewController do sfinalizowania go –

Powiązane problemy