如何删除以前的ViewController

时间:2014-08-03 21:12:31

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

我是一名学生,对编程很陌生。我想在业余时间学习Objective-C / Swift。我使用带有多个菜单/场景的swift的spriteKit制作了一个游戏。

我正在尝试从一个视图控制器转换到另一个视图控制器。为此,我使用了以下代码:

@IBAction func PlayButtonPressed(sender: AnyObject) {
    let playStoryboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let vc : UIViewController = playStoryboard.instantiateViewControllerWithIdentifier("playGame") as UIViewController
    self.presentViewController(vc, animated: true, completion: nil)
}

这适用于转换到新的VC场景,但是,我相信以前的VC仍然在堆栈中并占用内存,从而减慢了我的程序。

我已阅读其他一些帖子,您可以使用导航控制器删除VC。但是,我没有导航控制器;只查看控制器。我见过一些关于removeFromParentViewController()view.removeFromSuperview()的内容,但我真的不知道如何实现它。除此之外,我没有找到我正在寻找的答案。

所以我问的问题是如何从堆栈中删除以前的VC?任何帮助将是一个赞赏! (希望帮助很快,但Objective-C也有帮助)提前谢谢你!

请注意参考:我相信Objective-C我的代码看起来像这样:

-(IBAction) PlayButtonPressed: (id) sender {
    UIStoryboard *playStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    UIViewController *vc = [playStoryboard instantiateViewControllerWithIdentifier:@"playGame"];
    [self presentViewController:vc animated:YES completion:nil];
}

5 个答案:

答案 0 :(得分:16)

我可以假设,屏幕上显示的视图控制器是从主故事板自动实例化或通过设置应用程序的window.rootViewController属性实例化的。

在任何一种情况下,您都可以再次将rootViewController设为vc。要更改应用程序的rootViewController,您需要替换以下代码行:

self.presentViewController(vc, animated: true, completion: nil)

...下面是其中一个选项。

“导航”没有过渡动画:

<强>目标C

UIWindow *window = (UIWindow *)[[UIApplication sharedApplication].windows firstObject];
window.rootViewController = vc;

<强>夫特

let window = UIApplication.sharedApplication().windows[0] as UIWindow;
window.rootViewController = vc;

使用过渡动画“导航”:

<强>目标C

UIWindow *window = (UIWindow *)[[UIApplication sharedApplication].windows firstObject];
[UIView transitionFromView:window.rootViewController.view
                    toView:vc.view
                  duration:0.65f
                   options:UIViewAnimationOptionTransitionCrossDissolve // transition animation
                completion:^(BOOL finished){
                    window.rootViewController = vc;
                }];

<强>夫特

let window = UIApplication.sharedApplication().windows[0] as UIWindow;
UIView.transitionFromView(
    window.rootViewController.view,
    toView: vc.view,
    duration: 0.65,
    options: .TransitionCrossDissolve,
    completion: {
        finished in window.rootViewController = vc
    })

<强>说明: 一旦rootViewController值被更改,原始视图控制器引用计数应该变为0,因此它将从内存中删除!

答案 1 :(得分:2)

我想最好的实现方法是将以下内容放在上一个View Controller中 - Swift

    // Override to remove this view from the navigation stack
    override func viewDidDisappear(animated: Bool) {
        super.viewDidDisappear(animated)
        // Remove self from navigation hierarchy
        guard let viewControllers = navigationController?.viewControllers,
            let index = viewControllers.indexOf(self) else { return }
        navigationController?.viewControllers.removeAtIndex(index)
    }

答案 2 :(得分:2)

Swift 3

这将从存储器中删除当前视图控制器

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    guard let viewControllers = navigationController?.viewControllers,
    let index = viewControllers.index(of: self) else { return }
    navigationController?.viewControllers.remove(at: index)
}

答案 3 :(得分:1)

首先,您使用的是模态演示模式,而不是导航堆栈模式(UINavigationController)。你不能摆脱呈现视图控制器,也不应该,因为它会破坏导航。

这里简短的回答是,您不必担心这一点。视图控制器本身占用的内存量是微不足道的,并且一旦没有对它的引用(将其解除它或从导航堆栈中弹出),它将自动释放。

答案越长,取决于具体实施方式。如果你某种程度上无法增加堆栈的大小,那么这是一个问题。一个例子是,如果你有一个导航流程,你可以在两个&#34;屏幕之间自由移动&#34;但在内部,每个屏幕都会呈现一个新屏幕,而不仅仅是切换到现有屏幕。如果你遇到这样的事情,那么你最适合使用UITabBarController或类似的东西,你可以在视图控制器之间横向导航而不创建新的。

答案 4 :(得分:-1)

对于swift 3,您可以替换

self.present(ViewController(), animated: false, completion: nil);

if let window = UIApplication.shared.keyWindow{
            window.rootViewController = UINavigationController(rootViewController: ViewController());
        }