在释放未使用UIPageViewController页(Releasing unused pages

2019-08-16 19:44发布

我使用的是单独的.h.m.xib每个文件UIViewController一个基于网页UIPageViewController基于图画书。 每个页面加载动画,音乐等大约需要4MB内存。 在仪器,因为每个页面加载的空闲内存下落约4MB。 作为翻页这记忆永远不会释放。 它最终使内存警告。 UIPageViewController似乎保持它在内存中实例化的每个页面,并不会卸载它。 所以,当翻页速度快,应用程序崩溃。

我希望能够卸载除非需要3所有页面UIPageViewController -先前,当前和下一个页面。 我怎样才能卸载不需要的网页,因为他们被实例化UIPageViewController

下面是页面的阵列UIPageViewController从拉。 所有的页面(第1页,第二页等)的基本上只是加载图像文件,提供基本的动画,并有音乐。

    //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上面创建一个新的页面对象。

-(void)turnPageForward{

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

}

我曾尝试创建一个对象“ 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 ,但还没有找到任何接近。 最近被回“导航控制器 ‘但没有设置视图控制器以同样的方式’ARC不会释放时内存”。

我试着设置不需要页面到零,从而ARC可以没有运气删除它们。 任何建议或替代路径,我应该尝试? 我喜欢的页面卷曲效果,一直没能找到一个很好的其他地方,做水平卷页。

谢谢! 埃里克

Answer 1:

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

不,你这样做,通过实例所有这些“页”(控制器),并把它们放入一个数组(内存跳,你翻开新的一页,因为控制器的观点是不实际加载,直到你显示出来,即使控制器已被实例化。但是,一旦你这样做,你的控制器保留其观点和阵列保留控制器)。 你只需要保持某种你是哪个网页上计数,并在viewControllerBeforeViewController执行:和viewControllerAfterViewController :,实例化一个页面出现。 当您从页面消失,它的控制器将被dealloc'd。 如果加载很慢,则可能需要保留具有当前页面之前和之后的那些数组 - UIPageViewController不这样做,如果你有它设置为滚动,而不是页面卷曲过渡。

我做了一个简单的测试应用程序是这样的:

@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的方法日志,他们被称为当我导航离开他们。



Answer 2:

我知道这个问题是有点老,但也许我的方法可以帮助一些人不使用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];
        }
     }
}

您只释放他们,如果动作完成,否则下一个页面的变化,你会尝试访问发布网页是非常重要的。

希望这可以帮助!



Answer 3:

我遇到这个问题这一次。 而经过一个小时的思考,我必须找到一个解决方案。

这是我的.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和内存不会被滚动一次又一次增加。 希望这会帮助你。



文章来源: Releasing unused pages in UIPageViewController