Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何删除以前的ViewController_Ios_Objective C_Memory Management_Uiviewcontroller_Swift - Fatal编程技术网

Ios 如何删除以前的ViewController

Ios 如何删除以前的ViewController,ios,objective-c,memory-management,uiviewcontroller,swift,Ios,Objective C,Memory Management,Uiviewcontroller,Swift,我是一名学生,对编程相当陌生。我正试图在业余时间学习Objective-C/Swift。我用spriteKit和swift制作了一个有多个菜单/场景的游戏 我正在尝试从一个视图控制器转换到另一个视图控制器。为此,我使用以下代码: @IBAction func PlayButtonPressed(sender: AnyObject) { let playStoryboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)

我是一名学生,对编程相当陌生。我正试图在业余时间学习Objective-C/Swift。我用spriteKit和swift制作了一个有多个菜单/场景的游戏

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

@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?任何帮助都将不胜感激!(希望帮助以swift形式提供,但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];
}

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

简单的回答是,你不必担心这个问题。视图控制器本身占用的内存量很小,一旦不再有对它的引用(您可以将其取消或从导航堆栈中弹出),它就会自动释放


较长的答案取决于您的具体实现。如果您不知何故处于无限增加堆栈大小的情况下,那么这就是一个问题。例如,如果您有一个导航流程,您可以在两个“屏幕”之间自由移动,但在内部,每个屏幕都会显示一个新屏幕,而不仅仅是切换到现有屏幕。如果您遇到了类似的情况,那么您最适合使用
UITabBarController
或类似的工具,这样您就可以在视图控制器之间横向导航,而无需创建新的视图控制器。

我可以假设,屏幕上显示的视图控制器可以从主情节提要自动实例化,也可以通过设置应用程序的
窗口.rootViewController
属性实例化

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

self.presentViewController(vc, animated: true, completion: nil)
。。。使用以下选项之一

不带过渡动画的“导航”: 目标-C

UIWindow *window = (UIWindow *)[[UIApplication sharedApplication].windows firstObject];
window.rootViewController = vc;
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;
                }];
Swift

let window = UIApplication.sharedApplication().windows[0] as UIWindow;
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
    })
使用过渡动画“导航”: 目标-C

UIWindow *window = (UIWindow *)[[UIApplication sharedApplication].windows firstObject];
window.rootViewController = vc;
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;
                }];
Swift

let window = UIApplication.sharedApplication().windows[0] as UIWindow;
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,因此它将从内存中删除

我想最好的实现是将以下内容放在上一个视图控制器上-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)
    }

对于swift 3,您可以替换

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


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)
}

当我使用这段代码时,我看到我的视图在转换结束后重新定尺寸到正确的大小