10

I'm using a UISplitViewController every time I click on a row in the Master VC I can see that viewDidLoad() is run in the Detail VC.

Does this mean i'm creating a new instance of Detail VC each row click?

If so, how can I check that the Detail VC are unloading correctly and that i'm not just creating more and more new Detail VCs?

I'm a bit lost here in Swift. Previously I could NSLog in dealloc() and see the UIViewController correctly unloading.

I here Swift has a deinit function but this is never called:

deinit {
    println("\(__FILE__.lastPathComponent)) : \(__FUNCTION__)")
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

1) Where should I be removing my observers?

2) When I look in the Debug Navigator in Xcode the Memory usage just keeps going up and never down.

Updated: Detail VC is being called as follows:

if segue.identifier == "addEvent" {
    if let controller = (segue.destinationViewController as UINavigationController).topViewController as? ManageViewController {
        controller.manageEvent = nil
        controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
        controller.navigationItem.leftItemsSupplementBackButton = true
    }
}

I'm not doing anything different than lots of examples i've seen, but I am worried about deinit not being called

Updated: Working now - Problem was with delegate stopping deinit being called (see below answer)

My original Non-Working code was:

protocol ManageViewDelegate {
    func pressedButton(sender: AnyObject)
}

class ManageView: UIView {
    var delegate: ManageViewDelegate? = nil
    ...
}

New Working code:

protocol ManageViewDelegate: class {
    func pressedButton(sender: AnyObject)
}

class ManageView: UIView {
    weak var delegate: ManageViewDelegate? = nil
    ...
}
Richard
  • 1,688
  • 3
  • 16
  • 21
  • 1
    if `deinit` isn't being called, that means memory is being retained by *something* and isn't being released. You should edit your question to show how you are switching detail view controllers when each row is clicked. – Michael Dautermann Nov 16 '14 at 14:48
  • Updated, and how do you highlight certain words like you did with deinit? – Richard Nov 16 '14 at 14:59
  • 1
    You'll soon get to know how to use [StackOverflow's "markup" capabilities](http://stackoverflow.com/editing-help). – Michael Dautermann Nov 16 '14 at 15:02
  • 1
    Also, please note that the storyboard segue will always create a new instance of the destination view controller. – yusuke024 Nov 16 '14 at 15:12
  • What kind of segue are you using? – Michael Dautermann Nov 16 '14 at 15:27
  • Working now. Thank you for the help. Really appreciate it. – Richard Nov 16 '14 at 15:37
  • @Richard Is this `delegate` property in `manageView` something you created on your own? Usually you'd define delegates to be `weak`, which would avoid the need to manually set the `delegate` to `nil`. – Rob Nov 16 '14 at 16:43
  • Hi, yes, this is created by me as follows: var delegate: ManageViewDelegate? = nil; would "weak var delegate ...." be a better solution? – Richard Nov 16 '14 at 16:47
  • Would be great to reformat this question and give it an answer below - will show up in search results. – brandonscript Nov 16 '14 at 16:54

2 Answers2

26

You have a view with a delegate property that references back to the view controller. This will result in a strong reference cycle (previously known as a retain cycle) because the view controller is maintaining a strong reference to its top level view which is, in turn, maintaining a strong reference back to the view controller.

In the Resolving Strong Reference Cycles Between Class Instances section of The Swift Programming Language: Automatic Reference Counting, Apple describes how to address this:

Swift provides two ways to resolve strong reference cycles when you work with properties of class type: weak references and unowned references.

Weak and unowned references enable one instance in a reference cycle to refer to the other instance without keeping a strong hold on it. The instances can then refer to each other without creating a strong reference cycle.

Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialization.

Thus, you can resolve your strong reference cycle by defining the delegate to be weak:

weak var delegate: ManageViewDelegate? 

For that to work, you have to specify your protocol to be a class protocol:

protocol ManageViewDelegate: class {
    // your protocol here
}

That will resolve the strong reference cycle and eliminates the need to manually nil the delegate in order to resolve the strong reference cycle.

Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044
0

Also if you use blocks you need to add [weak self], otherwise,the view wouldn't be destroyed

 setupObserve(postID) {
        [weak self] chatRequest in
    self?.update()
 }

The deinit function should work out

Svitlana
  • 2,938
  • 1
  • 29
  • 38