UIPageViewController和移除当前视图控制器

5

我设置了UIPageViewController以在一些视图控制器之间前进和后退。我的问题是,当一个视图控制器添加到UIPageViewController时,内存使用量会增加,直到编译器给出Received memory warning,然后应用程序运行缓慢,直到应用程序清空内存并再次正常工作。如何在不增加内存的情况下导航视图控制器?或者更好地说,当添加新的视图控制器时,如何删除当前视图控制器?以下是我的代码:

// Create the page view controller.
self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageViewController"];
self.pageViewController.dataSource = self;


//disabling tap and swipe guesture
for (UIGestureRecognizer *recognizer in self.pageViewController.gestureRecognizers) {
    recognizer.enabled = NO;
}


// Instantiate the first view controller.
UIViewController *startingViewController = [self viewControllerAtIndex:0];

[self.pageViewController setViewControllers:@[startingViewController]
                                  direction:UIPageViewControllerNavigationDirectionForward
                                   animated:NO
                                 completion:^(BOOL finished) {
                                     // Completion code
                                 }];

// Add the page view controller to this root view controller.
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];

前进和后退操作:

- (void)goToPreviousContentViewController
{

    // Get index of current view controller
    UIViewController *currentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
    NSString *vcRestorationID = currentViewController.restorationIdentifier;
    NSUInteger index = [self.contentPageRestorationIDs indexOfObject:vcRestorationID];

    UIViewController *previousViewController = [self viewControllerAtIndex:index - 1];



    [self.pageViewController setViewControllers:@[previousViewController]
                                      direction:UIPageViewControllerNavigationDirectionReverse
                                       animated:NO
                                     completion:^(BOOL finished) {
                                         // Completion code
                                     }];
}

更多代码:
#pragma mark - UIPageViewControllerDataSource
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
    return self.contentPageRestorationIDs.count;
}





- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    NSString *vcRestorationID = viewController.restorationIdentifier;
    NSUInteger index = [self.contentPageRestorationIDs indexOfObject:vcRestorationID];

    if (index == 0) {
        return nil;
    }

    return [self viewControllerAtIndex:index - 1];
}




- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    NSString *vcRestorationID = viewController.restorationIdentifier;
    NSUInteger index = [self.contentPageRestorationIDs indexOfObject:vcRestorationID];

    if (index == self.contentPageRestorationIDs.count - 1) {
        return nil;
    }

    return [self viewControllerAtIndex:index + 1];
}






#pragma mark - Private Methods
- (UIViewController *)viewControllerAtIndex:(NSUInteger)index
{
    // Only process a valid index request.
    if (index >= self.contentPageRestorationIDs.count) {
        return nil;
    }

    // Create a new view controller.
    BaseContentViewController *contentViewController = (BaseContentViewController *)[self.storyboard instantiateViewControllerWithIdentifier:self.contentPageRestorationIDs[index]];

    // Set any data needed by the VC here
    contentViewController.rootViewController = self;

    return contentViewController;
}
3个回答

6

回答你的问题

  1. "如何在不增加内存的情况下导航视图控制器?"

    实际上无法做到这一点。当您加载新的视图控制器时,它将加载所有视图,并将视图控制器存储在内存中。您无法加载和显示不在内存中的视图控制器。

  2. "如何在添加新视图控制器时删除当前视图控制器?"

    您不应该这样做。空的视图控制器没有很大的内存占用,您可以轻松地在导航堆栈中拥有20多个视图控制器而不会出现任何内存问题。尽管可能实现这样的功能,但需要大量工作,而且并不能解决您问题的根源。

那么问题是什么?

您有一个内存管理问题。它不是由您发布的代码引起的,看起来很好。问题必须在您代码的另一部分中。

有两种常见情况可能导致内存管理问题:

  1. 保留循环:保留循环实际上是指两个对象相互保留。这违反了对象所有权的标准规则,使两个对象都无权释放另一个对象,从而导致内存泄漏(数字是保留计数):

  2. 不必要的缓存:如果您正在下载许多不同的图像并将它们缓存,那么这不是缓存的理想用例。缓存适用于存储频繁访问的对象。如果您没有经常访问这些图像或收到didReceiveMemoryWarning消息,则应释放这些对象。

如何调试内存问题

首先也是最简单的事情是重写视图控制器的dealloc方法。在视图控制器上重写dealloc方法将有助于确保在您期望时释放视图控制器。

-(void)dealloc {
    NSLog(@"viewcontroller is being deallocated");
 }

如果这个方法无法解决您的问题,您可以尝试使用Xcode工具调试并排除故障。 这篇文章 可以作为您开始调试的良好参考。


我没有下载任何东西,但感谢您的建议,我会检查它。 - iOS.Lover

3
为了避免内存问题和管理视图控制器,您需要将所有的视图控制器堆叠在一个容器中。这样,每次进行下一个/上一个调用时都会在该容器中进行,并提供您所需的功能。此容器的另一个好处是避免多次重新初始化控制器。
一旦将视图控制器添加到容器中,您就不需要再次对该控制器进行alloc init或初始化操作。
由于粘贴大量代码并不现实,而且无法查看Storyboard设置,因此我分享给您一个演示,以可视化和使用带有容器的页面控制器来容纳视图控制器。 PageDemo enter image description here

谢谢,你为每个视图控制器设置了导航控制器吗?如果是的话,那会让我的故事板更加复杂!我有27个视图控制器! - iOS.Lover
我刚刚在我的设备上检查了你的项目,结果是相同的!其实我的代码工作正常,它会自动释放内存,我只是想避免内存警告。 - iOS.Lover
这里的问题是视图控制器只有一个,适用于您所有的目的。我的意思是在Storyboard中不需要创建27个视图控制器。只需在Storyboard中创建一个控制器,并随着页面更改更改其详细信息即可。 - Kampai
不可能的,我的应用程序中每个视图控制器都有自己的内容、图片、动画、声音等。 - iOS.Lover
好的。如果所有这些细节都没有使用常见布局,那么在一个视图控制器中进行管理就很困难(特别是自动布局部分)。嗯,非常好,上面的答案将在内容共享公共UI或模式时完美运作。也许这些答案会对您有所帮助。 - Kampai

1
我在你的代码中没有看到任何内存问题。尝试使用名为“Leaks”的分析工具,查找未释放的对象。这里有一个官方苹果指南

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接