【问题标题】:UIViewController not being released from memory when poppedUIViewController 弹出时没有从内存中释放
【发布时间】:2014-04-20 00:12:56
【问题描述】:

我有一个UINavigationController,并且一旦另一个位于堆栈顶部的UIViewController,我就会尝试从内存中释放。我将UINavigationControllerviewControllers 属性分配给新的UIViewController,然后弹出它。这样我总是只有一个 UIViewController 在堆栈中。但是,每次我创建一个新的UIViewController 时,内存都会不断增加。调用了 Dealloc,但内存使用量保持不变。

您可以下载示例项目HERE

FirstViewController.h

#import "SecondViewController.h"

@interface FirstViewController : UIViewController

-(IBAction)goToSecond:(id)sender;

@end

FirstViewController.m

#import "FirstViewController.h"

@interface FirstViewController ()

@end

@implementation FirstViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"%@", self.navigationController.viewControllers);

}

-(void)goToSecond:(id)sender{

    SecondViewController *secondVC = [[SecondViewController alloc]init];
    [self.navigationController setViewControllers:@[secondVC]];
    [self.navigationController popViewControllerAnimated:NO];
}

-(void)dealloc{

    NSLog(@"FirstVC dealloc");
}
@end

SecondViewController.h

#import "FirstViewController.h"

@interface SecondViewController : UIViewController

-(IBAction)goToFirst:(id)sender;

@end

SecondViewController.m

#import "SecondViewController.h"

@interface SecondViewController ()

@end

@implementation SecondViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"%@", self.navigationController.viewControllers);

}

-(void)goToFirst:(id)sender{

    FirstViewController *firstVC = [[FirstViewController alloc]init];
    [self.navigationController setViewControllers:@[firstVC]];
    [self.navigationController popViewControllerAnimated:NO];

}

-(void)dealloc{

    NSLog(@"SecondVC dealloc");
}

@end

【问题讨论】:

  • 你为什么要这样做? UINavigation 栏会跟踪您的内存并按时释放正确的视图,如果您希望始终拥有一个视图控制器,请不要使用导航控制器。甚至不使用方舟,这样你就可以释放它。但我不建议你这样做。
  • 如果您想返回,那么应该首选简单的pushViewControllerpopViewController
  • @PiratM,你会建议什么来代替UINavigationController?我一次只需要一个ViewController
  • @YasKuraishi 我试过pushpopViewController 消耗的内存保持不变。您可以在示例项目中查看它。您可以看到创建 SecondViewController 时内存图是如何上升的,但是当它被弹出时,内存并没有减少。
  • @guardabrazo 您的应用中有多少个视图控制器?您是否需要所有这些“后退”功能?您需要释放它们的内存使用情况是什么?如果您只有几个 ViewContoller,您可以构建自己的假导航控制器。只有一个看起来完全一样的简单视图,但使用了 PresentView 控制器和dismissViewController。

标签: ios objective-c memory-management uiviewcontroller uinavigationcontroller


【解决方案1】:

导航控制器不应按预期使用。 您应该调用 pushViewControllerpopViewController 来显示/关闭您的视图控制器。 如果你有内存问题,尝试在didReceiveMemoryWarning回调中释放内存

【讨论】:

    【解决方案2】:

    我不确定 uinavigationcontroller 的好处,但无论如何你可以在你的 uiviewcontrollers 的 .m 中添加这个 sn-p

    -(void)viewDidAppear:(BOOL)animated{
        [super viewDidAppear:animated];    
        if (self.navigationController.viewControllers.count > 1) {
            NSMutableArray *newViewControllers = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
            [newViewControllers removeObject:[controllers objectAtIndex:1]];
            self.navigationController.viewControllers = newViewControllers;
        }
    }
    

    而不是

    [self.navigationController setViewControllers:@[firstVC]];
    [self.navigationController popViewControllerAnimated:NO];
    

    你可以设置

    [self.navigationController pushViewController:[[FirstViewController alloc] init] animated:NO];
    

    【讨论】:

      【解决方案3】:

      你正在使用 pop 走得更远,但如果你想去下一个ViewController,你需要使用push

      -(void)goToSecond:(id)sender{
          SecondViewController *secondVC = [[SecondViewController alloc]init];
          [ self.navigationController pushViewController:secondVC animated:YES];
      }
      

      SecondViewController 中要返回到您的FirstViewController,您应该使用pop

      -(void)backToController
      {
          [self.navigationController popViewControllerAnimated:YES];
      }
      

      你的情况

      -(void)goToFirst:(id)sender
       {
              [self.navigationController popViewControllerAnimated:YES];
       }
      

      【讨论】:

      • 我已经知道通常我应该使用push 更进一步,但它会将新的ViewController 添加到'UINavigationController` 的堆栈中,我想防止这种情况发生。
      • 如果你使用[self presentViewController:add animated:YES completion:nil]; 然后在SecondViewController 中添加一个新的UINavigationController ?
      • 我暂时无法尝试。你能详细说明一下代码吗?也许在一个单独的答案中?我会尽快测试它
      【解决方案4】:

      我在 GitHub 上上传了一个简单的应用程序,带有我在评论中谈到的假导航栏,希望它对您的需求有所帮助:https://github.com/yosihashamen/HelpersApps

      请注意,您必须始终保持“BaseViewController”处于活动状态。

      【讨论】:

        【解决方案5】:

        我的意思是这样的。

        在您的FirstViewController 中使用presentViewController 而不是push,将新的UINavigationController 添加到SecondViewController

        -(void)goToSecond:(id)sender{
            SecondViewController *secondVC = [[SecondViewController alloc]init]; 
            UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:secondVC];
            [self presentViewController:nav animated:YES completion:NIL];
        
        }
        

        SecondViewController 中将UIBarButtonItem 添加到Navigation bar

        UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStyleDone target:nil action:@selector(goToFirst:)];
        self.navigationItem.backBarButtonItem = backButton;
        

        并实现dismiss方法。

        -(void)goToFirst:(id)sender
         {
            [self dismissViewControllerAnimated:YES completion:NULL];
         }
        

        【讨论】:

          【解决方案6】:

          试试setViewControllers:animated:

          这允许您在 UINavigationController 堆栈上显式设置视图控制器,就像您正在做的那样,它会自动处理导航动画,而无需您调用 popViewControllerAnimated:

          如果您有一个多视图旅程,您需要摆脱目前已显示的屏幕但保持导航动画(例如启动时的应用演示),或者如果您想轻松推送多个立即查看导航堆栈上的控制器。

          这里是苹果文档:https://developer.apple.com/library/ios/documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html#jumpTo_21

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-08-27
            • 2023-04-10
            • 2015-08-13
            • 1970-01-01
            • 2018-10-26
            • 1970-01-01
            • 1970-01-01
            • 2019-12-18
            相关资源
            最近更新 更多