UIPageViewController memory leak

时光毁灭记忆、已成空白 提交于 2019-12-17 23:14:23

问题


It seems that UIPageViewController is holding the initial content view controller forever. For example:

DataViewController *startingViewController = [self.modelController viewControllerAtIndex:0 storyboard:self.storyboard];
NSArray *viewControllers = @[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];
self.pageViewController.dataSource = self.modelController;

The startingViewController is never released until the pageViewController itself it released.

To reproduce this bug, just create a new project in XCode using the Page-Based Application template. And add 3 lines of code into DataViewController.m

@property NSInteger debugIndex; // file scope
NSLog(@"DataViewController[%d] created", self.debugIndex); // in viewDidLoad
NSLog(@"DataViewController[%d] dealloc", self.debugIndex); // in dealloc

And when you scroll the demo App in vertical orientation, you'll get logs like this:

DataViewController[0] created  
DataViewController[1] created  
DataViewController[2] created  
DataViewController[1] dealloc  
DataViewController[3] created  
DataViewController[2] dealloc  
DataViewController[4] created  
DataViewController[3] dealloc  
DataViewController[5] created  
DataViewController[4] dealloc  
DataViewController[6] created  
DataViewController[5] dealloc  

DataViewController[0] is never deallocated.

Any ideas about this? Thanks!


回答1:


Are you using transitionStyle UIPageViewControllerTransitionStyleScroll? I encountered the same or a similar problem which seemed to disappear when using page curl animations instead.

The problem was compounded for me because I was allowing a UISliderBar to set the position in the content. So on change of the UISliderBar, I was calling setViewControllers:direction:animated:completion: which caused more and more view controller references to get "stuck" in my UIPageViewController.

I am also using ARC. I have not found an acceptable way to force the UIPageViewController to let go of the extra view controller references. I will probably either end up using the page curl transition or implementing my own UIPageViewController equivalent using a UIScrollView with paging enabled so I can manage my own view controller cache instead of relying on UIPageViewController's broken view controller management.




回答2:


I'm not sure you still got the problem, but I had the same problem and I found the solution.

I don't know the reason, but it works.

I'm setting the first viewController right after addSubview, rather than before addChlidViewController.

-(void)settingPageViewController{
if (!self.pageViewController) {
    self.pageViewController = [[UIPageViewController alloc]initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
    self.pageViewController.delegate = self;
    self.pageViewController.dataSource = self;
    [self addChildViewController:self.pageViewController];
    [self.pageViewController didMoveToParentViewController:self];
    [self.containerView addSubview:self.pageViewController.view];
    [self.pageViewController setViewControllers:@[[self viewcontrollerAtIndex:0]] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
}    
}

and the first viewController will dealloc in the right time.

also, I found if call

        [self.pageViewController setViewControllers:@[[self viewcontrollerAtIndex:0]] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:^(BOOL finished){
        NSLog(@"finished : %d",finished);
    }];

before addSubView and the completion block will not call.

and I reckon this block is the reason why the first viewController didn't dealloc.

I'll go find out why it didn't callback, and improve the answer~

cheers




回答3:


After a few attempts to figure out what was happening on a similar issue, I noticed that in my project there were 2 reasons that caused a retain problem and resulted in having a UIPageViewController being forever retained.

1) there was a circular reference between the UIPageViewController and the UIViewcontroller that was presented (this was fixed by changing the properties to weak from strong in both classes)

2) and the main fix consisted in changing

[self setViewControllers:@[initialDetailsViewController] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];

to

__weak __typeof__(self) weakSelf = self;
    [weakSelf setViewControllers:@[initialDetailsViewController] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];

I hope this helps someone




回答4:


same problem here i resolved it by keeping my initial viewController in the variable and instead of creating the same vc on particular pageIndex i just reuse it




回答5:


I had same problem and solved the following:

[startingViewController release]; where the end point of initialization.

then the first ViewController will be deallocated.



来源:https://stackoverflow.com/questions/15156254/uipageviewcontroller-memory-leak

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!