Liberación de páginas no utilizadas en UIPageViewController

Estoy usando files separados .h , .m y .xib para cada página basada en UIViewController de un libro de imágenes basado en UIPageViewController . Cada página está cargada de animaciones, música, etc. y toma aproximadamente 4MB de memory. En Instrumentos, la memory libre baja aproximadamente 4MB a medida que se carga cada página. Esta memory nunca se libera a medida que se giran las páginas. Eventualmente da advertencias de memory. UIPageViewController parece mantener cada página que crea en la memory y no la downloadá. Entonces, cuando las páginas se vuelven rápidas, la aplicación se bloquea.

Me gustaría poder download todas las páginas excepto las 3 que necesita UIPageViewController : las páginas anteriores, actuales y siguientes. ¿Cómo puedo download páginas no deseadas ya que fueron instanciadas por UIPageViewController .

A continuación se muestra la matriz de las páginas de la que UIPageViewController saca. Todas las páginas (Página1, Página2, etc.) básicamente solo cargan files de image, proporcionan animation básica y tienen música.

  //ARRAY OF PAGES pageArray = [[NSArray alloc] initWithObjects: (id)[[Page1 alloc] initWithNibName:nil bundle:nil], [[Page2 alloc] initWithNibName:nil bundle:nil], [[Page3 alloc] initWithNibName:nil bundle:nil], [[Page4 alloc] initWithNibName:nil bundle:nil], [[Page5 alloc] initWithNibName:nil bundle:nil], [[Page6 alloc] initWithNibName:nil bundle:nil], [[Page7 alloc] initWithNibName:nil bundle:nil], [[Page8 alloc] initWithNibName:nil bundle:nil], // continues all the way up to page 47 [[Page47 alloc] initWithNibName:nil bundle:nil], nil]; 

He UIPageViewController initialization estándar para UIPageViewController . Utiliza " nextPageNumber " para extraer la página correcta de la pageArray anterior para crear un nuevo object de página.

 -(void)turnPageForward{ [pageController setViewControllers:[NSArray arrayWithObject:[pageArray objectAtIndex:nextPageNumber]] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:^(BOOL finished){ }]; 

}

He intentado crear un object " pageIndex " (ver más abajo) que se establece en nil después de proporcionarlo al pageController . No funcionó. La página seguía ocupando la memory mucho después de que las páginas habían avanzado.

 //PROGRAM PAGE FORWARD 

– (void) turnPageForward {

 UIViewController * pageIndex =[pageArray objectAtIndex:nextPageNumber]; //nextPageNumber is the next page to load [pageController setViewControllers:[NSArray arrayWithObject:pageIndex] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:^(BOOL finished){ }]; pageIndex = nil; 

}

He revisado stackoverflow para publicaciones que usan la misma forma de suministrar páginas a UIPageViewController , pero no he encontrado nada UIPageViewController . Lo más cercano fue " ARC no liberando memory cuando se" retrocede "en el controller de navigation ", pero no establece los controlleres de vista de la misma manera.

He intentado configurar las páginas no deseadas en cero para que ARC pueda eliminarlas sin suerte. ¿Alguna sugerencia o paths alternativos que debo probar? Me gusta el efecto de curvatura de página y no he podido encontrar uno bueno en otro lugar que haga curvas de página horizontal.

¡Gracias! Eric

"UIPageViewController parece mantener cada página que crea en la memory"

No, lo está haciendo instanciando todas esas "páginas" (controlleres) y colocándolas en una matriz (la memory salta mientras gira la página porque la vista del controller no está realmente cargada hasta que la visualiza, a pesar de que el controller ha sido instanciado. Pero una vez que haya hecho eso, su controller conserva su vista y la matriz conserva el controller). Solo necesita mantener algún tipo de count de la página en la que se encuentra, y en la implementación de viewControllerBeforeViewController: y viewControllerAfterViewController :, instale una página allí. Cuando abandones esa página, su controller quedará desarmado. Si la carga es lenta, es posible que necesite mantener un set que tenga la página actual y los antes y después: UIPageViewController hace eso si lo tiene configurado para desplazarse en lugar del curl de página para la transición.

Hice una sencilla aplicación de testing como esta:

 @implementation ViewController { int count; } - (void)viewDidLoad { [super viewDidLoad]; count = 1; self.pager = [[UIPageViewController alloc]initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationDirectionForward options:nil]; self.pager.dataSource = self; self.pager.delegate = self; Page1 *first = [[Page1 alloc] initWithNibName:@"Page1" bundle:nil]; [self.pager setViewControllers:@[first] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; [self addChildViewController:self.pager]; [self.view addSubview:self.pager.view]; [self.pager didMoveToParentViewController:self]; } -(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { if (count > 1) { NSString *nibName = [@"Page" stringByAppendingFormat:@"%d",count-1]; UIViewController *prev = [[NSClassFromString(nibName) alloc] initWithNibName:nibName bundle:nil]; count -= 1; return prev; } return nil; } -(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { if (count < 3) { NSString *nibName = [@"Page" stringByAppendingFormat:@"%d",count+1]; UIViewController *next = [[NSClassFromString(nibName) alloc] initWithNibName:nibName bundle:nil]; count += 1; return next; } return nil; } 

Mi ejemplo solo tiene 3 páginas, pero ilustra una forma de hacerlo. Puse los logs en los methods dealloc de los 3 controlleres, y fueron llamados cuando me alejé de ellos.

Sé que esta pregunta es un poco más antigua, pero tal vez mi enfoque puede ayudar a algunas personas que enfrentan el mismo problema cuando no usan ARC.

Creo que la mejor manera de liberar páginas no utilizadas está en el método didFinishAnimation del UIPageViewController. Obtiene el 1 o 2 controlleres de vista anteriores allí y puede liberarlos fácilmente. Lo hago así:

 -(void)pageViewController:(UIPageViewController *)thePageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed { if(completed) { for (UIViewController *viewController in previousViewControllers) { [viewController release]; } } } 

Es importante que solo los lance si la acción se completó porque, de lo contrario, con el cambio de página siguiente, intentaría acceder a las páginas liberadas.

¡Espero que esto ayude!

Me encuentro con este problema esta vez. Y después de una hora pensando, había encontrado una solución.

Este es mi file .h

 #import <UIKit/UIKit.h> @interface BKContentViewController : UIPageViewController @end 

Y mi file .m y el método viewDidload

 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. self.delegate = self; self.dataSource = self; [self setViewControllers:[NSArray arrayWithObject:detailContent] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL]; } 

Y lo mas importante.

 #pragma mark - UIPageViewControllerDataSource UIPageViewControllerDelegate - (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{ if (completed) { [self setViewControllers:[NSArray arrayWithObject:detailContent] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL]; } } - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{ if (!detailRight) { detailRight = [[DetailContent alloc] init]; [detailRight setShouldReturn:YES]; [detailRight setPath:fPath withFileName:fName]; } return detailRight; } - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController{ if (!detailLeft) { detailLeft = [[DetailContent alloc] init]; [detailLeft setShouldReturn:YES]; [detailLeft setPath:fPath withFileName:fName]; } return detailLeft; } - (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation{ UIViewController *currentViewController = [self.viewControllers objectAtIndex:0]; NSArray *viewControllers = [NSArray arrayWithObject:currentViewController]; [self setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL]; self.doubleSided = NO; return UIPageViewControllerSpineLocationMin; } 

Después de esto, solo tengo tres viewContrller y la memory no boostá al desplazarme una y otra vez. Espero que esto te ayudará.