Why doesn't evading the view controller clear the exposed controller from memory?

I have 2 controllers. Each of them has only one button on the screen. For the first controller button, the modal second controller is displayed, and for the second controller button, the presented controller is rejected.

The first code is as simple as a door:

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

      

The second controller code contains additional code to detect if the controller still exists after firing.

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

      

And all the code of the second controller looks like this:

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

      

So when you run this and press the button on the first screen of the controller for the first time, then every 5 seconds you will see something like this in the console:

Proj.WebViewController index class is 0

But if you fire the dispatcher and the gift again, then you will see both:

Proj.WebViewController index class is 0

Proj.WebViewController index class is 1

As I understand it, the firing is not removed from the memory presented by the controller, even if no one catches it from my end.

Does anyone know what this is and how can I solve it?

You can also download a sample project

+3


source to share


3 answers


the timer catches your view controller

you should leave a weak reference for the timer and add timer.invalidate()

todismissSelf



https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/index.html#//apple_ref/occ/instm/NSTimer/invalidate

+3


source


In a swift, if your object is being used, the compiler understands that it will be used like that even if you dismissViewControllerAnimated

UIViewController

. he won't dealloc

. so you need a invalidate()

timer to dismissViewControllerAnimated

. and is dealloc

replaced by deinit

.

@IBAction func dismissSelf() {
        timer.invalidate()
        self.dismissViewControllerAnimated(true, completion: nil)
    }

deinit {

        self.view.removeFromSuperview()
        println("call")
        // perform the deinitialization
    }

      



Hope it helps you.

+1


source


More details

swift-nstimer-tutorial-lets-create-a-counter-application & amp; simple-stopwatch-app-in-swift

NSTimer_Class

Use this ...

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

      

0


source







All Articles