为什么解雇视图控制器未从内存中清除显示的控制器?

问题描述 投票:4回答:4

我有2个控制器。每个屏幕上只有一个按钮。对于第一控制器,按钮以模态呈现第二控制器,而对于第二控制器按钮则解除呈现的控制器。

第一个代码很简单,如门:

class ViewController: UIViewController {
    @IBAction func present(sender: AnyObject) {
        let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
        if let controller = storyboard.instantiateViewControllerWithIdentifier("web") as? UIViewController {
            controller.modalTransitionStyle = UIModalTransitionStyle.FlipHorizontal
            self.presentViewController(controller, animated: true, completion: nil)
        }
    }
}

第二控制器代码包含一些额外的代码,用于检测解雇控制器后仍然存在。

static var index: Int = 0
var index: Int

required init(coder aDecoder: NSCoder) {
    self.index = WebViewController.index++
    super.init(coder: aDecoder)
    let timer = NSTimer.scheduledTimerWithTimeInterval(5, target: self, selector: "action", userInfo: nil, repeats: true)
}

func action() {
    NSLog("Class \(self.dynamicType) index is \(self.index)")
}

第二个控制器的所有代码如下:

class WebViewController: UIViewController {
    static var index: Int = 0
    var index: Int

    required init(coder aDecoder: NSCoder) {
        self.index = WebViewController.index++
        super.init(coder: aDecoder)
        let timer = NSTimer.scheduledTimerWithTimeInterval(5, target: self, selector: "action", userInfo: nil, repeats: true)
    }

    func action() {
        NSLog("Class \(self.view) index is \(self.index)")
    }

    @IBAction func dismissSelf() {
        if let presentingController = self.presentingViewController {
            presentingController.dismissViewControllerAnimated(true, completion: nil)
        }
    }
}

因此,当您第一次运行此程序并在第一个控制器屏幕上按按钮时,每5秒钟您将在控制台中看到类似以下内容的东西:

Class Proj.WebViewController索引为0

但是如果您将控制器解雇并且再次出现,那么您将同时看到这两者:

Class Proj.WebViewController索引为0

Class Proj.WebViewController索引为1

据我所知,即使没有人从我身边抓住他,也不表示不会从内存中删除控制器。

有人知道这是什么,我该如何解决?

也可以下载sample project

ios cocoa-touch swift uikit
4个回答
3
投票

计时器正在捕获您的视图控制器

您应在计时器中保留弱引用,并在timer.invalidate()]中添加[C0

dismissSelf


1
投票

快速地,如果您的对象被利用,那么编译器将理解它会被使用,因此即使您https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/index.html#//apple_ref/occ/instm/NSTimer/invalidate也是dismissViewControllerAnimated。不会是UIViewController。因此您需要在触发dealloc之前先使用invalidate()计时器。 dismissViewControllerAnimated被替换为dealloc

deinit

希望对您有帮助。


0
投票

阅读更多

@IBAction func dismissSelf() { timer.invalidate() self.dismissViewControllerAnimated(true, completion: nil) } deinit { self.view.removeFromSuperview() println("call") // perform the deinitialization } swift-nstimer-tutorial-lets-create-a-counter-application

simple-stopwatch-app-in-swift

使用此...

NSTimer_Class

0
投票

我也遇到过这样的背景:“为什么解雇视图控制器不从内存中清除显示的控制器?”。因此,就我而言,我有

@IBAction func dismissSelf() {
        if let presentingController = self.presentingViewController {
            timer.invalidate()// add this
            presentingController.dismissViewControllerAnimated(true, completion: nil)
        }
    }

我的SecondViewController上的上面的代码没有调用deinit

修复了我的问题:

FirstViewController: UIViewController {
var secondViewController: SecondViewController
 override func viewDidLoad() {
      super.viewDidLoad()
      //Important...Don't Do instantiation here....
      //Instantiate only when it's going to be used
      secondViewController = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController
 }
 @IBAction fun buttonAction() {
     self.present(secondViewController, animated: true)
 }
}

SecondViewController的引用将保留在SecondViewController变量上,直到对其重新初始化或设置为nil为止。

© www.soinside.com 2019 - 2024. All rights reserved.