在UIPageViewController中释放未使用的页面

我为基于UIPageViewController的图片书的每个基于UIViewController的页面使用单独的.h.m.xib文件。 每个页面加载animation,音乐等,大约需要4MB的内存。 在乐器中,随着每个页面的加载,可用内存下降大约4MB。 这个内存从不被释放,因为页面被转动。 它最终会给出内存警告。 UIPageViewController似乎保持它在内存中实例化的每个页面,并不会卸载它。 所以,当页面变快,应用程序崩溃。

我希望能够卸载除UIPageViewController所需的3个页面之外的所有页面 – 前一页,当前页和下一页。 我怎样才能卸载不受欢迎的页面,因为它们是由UIPageViewController实例化的。

以下是UIPageViewController取出的页面的数组。 所有的页面(Page1,Page2等)基本上只是加载图像文件,提供基本的animation,并有音乐。

  //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]; 

我遗漏了UIPageViewController的标准初始化。 它使用“ nextPageNumber ”从上面的pageArray拉出正确的页面来创build一个新的页面对象。

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

}

我已经尝试创build一个对象“ pageIndex ”(见下文)设置为零后提供给pageController 。 它没有工作。 页面进入后页面仍然占用内存。

 //PROGRAM PAGE FORWARD 

– (无效)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; 

}

我已经通过使用提供页面到UIPageViewController相同的方式,但没有发现任何closures通过stackoverflow看post。 最接近的是“ 导航控制器 ”中的“ ARC不释放内存”,但不以相同的方式设置视图控制器。

我试图设置不需要的页面为零,所以ARC可以删除它们没有运气。 任何build议或备用path,我应该尝试? 我喜欢页面curl的效果,并没有find一个好的一个水平页面curl的地方。

谢谢! 埃里克

“UIPageViewController似乎保持每个页面在内存中实例化”

不,你是通过实例化所有这些“页面”(控制器),并把它们放到一个数组中(内存跳转,因为控制器的视图实际上并没有加载,直到你显示它,即使控制器已经被实例化了,但是一旦你这样做了,你的控制器就保留了它的视图,而数组保留了控制器)。 你只需要保持某种页面的计数,并在viewControllerBeforeViewController:和viewControllerAfterViewController:的实现中,在那里实例化一个页面。 当你离开该页面时,其控制器将被解除分配。 如果加载速度较慢,则可能需要保留一个具有当前页面和前后页面的数组 – 如果将UIPageViewController设置为滚动而不是页面curl,则可以使用UIPageViewController。

我做了这样一个简单的testing应用程序:

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

我的例子只有3页,但它说明了一个方法来做到这一点。 我把日志放在3个控制器的dealloc方法中,当我离开它们时,它们被调用。

我知道这个问题有点老,但也许我的方法可以帮助一些人在不使用ARC时面临相同的问题。

我认为释放未使用页面的最好方法是在UIPageViewController的didFinishAnimation方法中。 你得到1或2个先前的视图控制器,你可以很容易地释放它们。 我这样做:

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

如果操作完成,只释放它们是非常重要的,否则在下一页更改时您会尝试访问已发布的页面。

希望这可以帮助!

我这次遇到这个问题。 经过一个小时的思考,我find了解决办法。

这是我的.h文件

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

和我的.m文件和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]; } 

而最重要的。

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

在此之后,我只有三个viewContrller和内存不会一再滚动增加。 希望这会帮助你。