10

There are some retain cycle in my iOS application.

For a particular viewController, stuck in a retain cycle, I have tried making all delegates weak. But when I simulate memory warning from simulator , didRecieveMemoryWarning is called , but deinit method is not called .

I want to print/see the owner of that viewController that is still holding it when didRecieveMemoryWarning is called. Is there any way I can do this.

ila
  • 920
  • 12
  • 35
  • 1
    I may be wrong, but I don't think that you can. – Have you tried to profile with the "Leaks" instrument? That can show retain cycles. – Martin R Dec 21 '15 at 13:34
  • 1
    I don't know a direct way but, if you run the app with Instruments attached and use the Allocations template, you can look at individual objects and see their history. – Phillip Mills Dec 21 '15 at 13:38
  • Note that receiving a memory warning does not imply anything is automatically deallocated: it's up to you to release any objects you hold strong references to and either no longer need, or are able to re-create whenever they are needed. The view controller itself will only be deallocated once it has been removed from the view controller hierarchy. – jcaron Dec 21 '15 at 13:54
  • did you use nstimer in your controller? if YES make sure invalidate this timer when controller not use – larva Dec 21 '15 at 14:10

3 Answers3

24

If you are on Xcode 8 you can use the Memory Graph Debugger to visually see the active memory graph for objects in your projects. You can get to the Memory Graph Debugger by using the three circle icon shown below. enter image description here

The Memory Graph Debugger was highlighted at WWDC 2016 in the following lecture, starting around 24:30.

https://developer.apple.com/videos/play/wwdc2016/410/

weber
  • 567
  • 1
  • 6
  • 14
6

No there is not a way to print the owners of an object as you describe, at least not exactly. iOS does not use garbage collection, it uses ARC (Automatic Reference Counting.) The system doesn't track owning references in ARC. Instead, each time you add an owning reference to an object the system increases a retain count, and every time you clear an owning reference the system decrements that retain count.

What you can do, though, is run your program with the memory instrument. (There is a debugging application called "Instruments", you pick a debugging template called an "instrument" that you use within the Instruments program.) With the memory instrument you can follow the life-cycle of an object, as well as tracking the number of active objects in your app's heap.. When you select an object in the list of currently active object you can see where in your program it was allocated and where the code that creates strong references comes from. Explaining how to use Instruments is beyond the scope of an SO post however. There are various tutorials and WWDC session videos on the subject. I suggest doing some searching.

As to your question, forcing a low memory warning would not cause an active view controller (one that is on-screen) to be released and it's deinit method to be called. The system maintains a strong reference to the view controller.

Also, you should make delegate references weak by default. Having a delegate reference be a strong reference is VERY unusual. I've only seen it once or twice, for specific reasons.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
-2

You can make a print on the deinit method like

class Person {
    let name: String
    init(name: String) {
        self.name = name
        print("\(name) is being initialized")
    }
    deinit {
        print("\(name) is being deinitialized")
    }
}

You can check this: Automatic Reference Counting

marchiore
  • 582
  • 2
  • 6
  • 21