I have a problem with objects not being 'deallocked', does anyone know of a way to see the reference count chart in either Xcode or Instruments? I know how to do this in the leaks template in Instruments, but strangely, Leaks detects nothing. I do think there is a leak though.
If Instruments says there is no leak, then it surely is right (except if you managed to produce a retain cycle). You can peak at [obj retainCount], but it is strongly discouraged to do so.
Remember that you can create "leaks" for example by putting stuff into NSMutableArrays or NSMutableDictionaries and never removing them. These kind of leaks won't show up Instruments. Same for retain cycles. So you should look for these problems.
Related
I have deinit method in all my VCs to check if they are being deinitialized or not
deinit {
print("\(self.description) successfully deinitialized")
}
When I logout, I see all my view controllers are deinitialized and my LoginViewController becomes the root view controller. But I can still see the RAM usage as 90MB. Every time I log in and logout, it keeps increasing.
Is it possible if my view controller has deinitialized, still it can have a memory leak?
What I know is, if the view controller is deinitialized, there is no memory leak. If there is a memory leak, the view controller will not deinitialize.
Am I wrong? Please help.
UPDATE: As per Luca's suggestion, and with the help of this answer, I found out the memory leaks. But I am not able to understand any of this. Is there any way to make it more readable?
There are three types of undesired memory issues:
Abandoned memory: This is memory that you do have some lingering strong references, but for which you no longer have access to these references. The typical example is a strong reference cycle.
This is very common problem in Swift projects. You find these using the “Debug Memory Graph” feature. See iOS app with ARC, find who is owner of an object or How to debug memory leaks when Leaks instrument does not show them?.
By the way, you’ve apparently confirmed that your view controllers are being released. That’s great if that’s the case. But they’re not the only object that can be entangled in a strong reference cycle. Any reference types can get caught up in reference cycles. Use the “Debug Memory Graph” feature and review your objects in the left panel and make sure there’s nothing there that shouldn't be. (By the way, this technique saves you from having to sprinkle deinit methods all over the place.)
Cached memory: This is memory that has been allocated, and the system will hang on to it in case you might need it again, offering you high performance access. This often isn’t too worrisome unless the amount of memory consumed is huge, because when the device is placed in memory pressure, often this memory is reclaimed automatically for you.
If you use UIImage(named:) that can cache images in memory. If you use URLSession, the URLCache can cache responses.
If testing on simulator, you might want to choose “Debug” » “Simulate Memory Warning” and see how much memory is retrieved, if any.
Leaked memory: This is memory that that has been allocated, but for which you have no further references to it. Typically this is a result of some manual allocation of memory that was never deallocated.
The Leaks tool will help you find these, but this is relatively uncommon to have anything material in this category in Swift code. (Or if you do have them, they tend to be small things generated within the frameworks, not within your control.) Sure, if you’re doing manual Core Foundation (or Core Graphics) calls, you can manifest these sorts of issues, but it’s not very common.
FWIW, the leaks tool doesn’t appear to be reporting any material memory consumption. So focus on Allocations tool (or, better, the “Debug Memory Graph”, if you can). Your leaks don’t appear to be enough to account for the sort of memory loss that you’re talking about here.
Also, I’d suggest you confirm that you do not have memory diagnostics turned on. E.g. things like zombies or the like can cause growth in memory (though I wouldn’t have thought that you could approach 90mb worth). Tools like this, the malloc stack trace, etc., increase memory consumption. That’s fine while using these tools to diagnose issues, but should be turned off when you’re done.
But, bottom line, I’d focus on confirming that the problem is not abandoned or cached memory, before diving into leaks (as often the latter are small and unrelated to anything in your code). These are far more common source of issues.
Even though the ViewController is de-initialised it doesn't necessarily mean it will be deallocated. There is a possibility there is a strong reference cycle. Or maybe in your code, to avoid retain cycle you are using unowned reference somewhere, for which the reference count is not becoming zero. The object will not be de-allocated until both strong and unowned reference counts become zero. In that case try using weak instead of unowned and see if it works. Weak references point to something called side table instead of directly pointing to the object, and hence don't keep the object from getting deallocated once de-initialised
Check out this article to understand how unowned reference can sometimes keep the object from getting deallocated, and ARC in general.
As I start working in swift, I am curious in memory mgmt. As we all know that during any object creation or assignment of data into that object it takes memory. How can we check that a particular object has released the memory. I used xcode memory report to see memory status and fluctuations.
Here is a sample of images:
How can release memory if I already set nil into the objects.
Use instruments to track the lifecycle of an object than just Xcode because it gives you the allocation details at much higher level.
Check out the answer at https://stackoverflow.com/a/14891837/5133769. Though it was explained with old instruments it still works.
Some objects are very small and it could be difficult to see in Memory profiling which one is released. This tool is helpful for finding memory leaks in an app. To check was some object released from memory or wasn't you can setup breakpoints or logs in dealloc() method for objective c and in deinit() method for swift.
Using instruments checking for leaks or allocations is the recommended way.
You can also set breakpoints or add logs to the dealloc method.
It's the first time I have to fix a memory problem from one of my iOS apps, so I'm not really sure how to track it, I've been reading some post from different blogs and I've found that my memory is constantly increasing:
The problem is that I don't know how to track and fix the problems in my code, and I also don't know what should be the best "Growth" in memory. Thank you.
First, I'd recommend watching WWDC 2013 Fixing Memory Problems and WWDC 2012 iOS App Performance: Memory videos. They are dated, yet still relevant, demonstrating of taking the above screen snapshot down to the next level in order to identify the underlying source of the memory issue.
That having been said, I have a couple of observations:
In my experience, nowadays, the problem is rarely "leaked memory" (i.e. memory that has been allocated, for which there are no more references, but you neglected to free it). It's rather hard to leak in Swift (and if you use the static analyzer on Objective-C code, the same it true there, too).
The more common problem is "abandoned memory" resulting from strong reference cycles, repeating timers not getting invalidated, circular references between view controller scenes, etc. These won't be identified by the Leaks tool. Only by digging into the Allocations tool.
First, I often like to see what accounts for the bulk of the abandoned memory. So I double click on a top level call tree and it will show me where the abandoned memory was allocated:
Note, this doesn't tell me why this was abandoned, but by knowing where the bulk of the abandoned memory was allocated, it gives me some clues (in this example, I'm starting to suspect the SecondViewController).
I then drill into the generations results and start by looking for my classes in the allocations (you can also do this by manually selecting a relevant portion of the allocations graph, as discussed here). I then filter the results, searching for my classes here. Sure, this won't always be the most significant allocation, but in my experience this sort of abandoned memory almost always stems from some misuse of my classes:
Again, this is pointing me to that SecondViewController class.
Note, when looking at generations, I generally ignore the first one or two generations because they may have false positives stemming from the app "warming up". I focus on the latter generations (and make sure that I only "mark" a generation when the app has been returned to some-steady, quiescent state.
For the sake of completion, it's worth pointing out that it's sometimes useful running Instruments with the "Record reference counts" feature on the unreleased allocation:
If you do that, you can sometimes drill into the list of retain and release calls and identify who still has the strong reference (focus on unpaired retain/release calls). In this case it's not very useful because there are just too many, but I mention in because sometimes this is useful to diagnose who still has the strong reference:
If you're using Xcode 8, it has a brilliant object graph debugger that cuts through much of this, graphically representing the strong references to the object in question, for example:
From this, the problem jumps out at me, that I not only have the navigation controller maintaining a reference to this view controller, but a timer. This happens to be a repeating timer for which I neglected to invalidate. In this case, that's why this object is not getting deallocated.
In the absence of Xcode 8's object graph debugger, you're left to pouring through the retain and release references (and you can look at where each of those strong references were established and determine if they were properly released) or just looking through my code for things that might be retaining that particular view controller (strong reference cycles, repeating timers, and circular view controller references are the most common problems I see).
Minimizing your app's Memory Footprint
For the benefit of both stability and performance, it's important to understand and heed the differing amounts of memory that are available to your app across the various devices your app supports. Minimizing the memory usage of your app is the best way to ensure it runs at full speed and avoids crashing due to memory depletion in customer instantiations. Furthermore, using the Allocations Instrument to assess large memory allocations within your app can sometimes be a quick exercise that can yield surprising performance gains.
Apple Official Document
i am working on project in which application memory usage increase continuously even i am on same view and app in idle
i am using ARC, dealloc also not called.
most on my properties are nonatomic and retain.
XCode has a built-in memory profiler that can help you with this issue - for a tutorial on how to use it, this might be helpful http://www.raywenderlich.com/23037/how-to-use-instruments-in-xcode
Otherwise, if dealloc isn't being called it could be a symptom of a retain cycle (two objects maintain strong references to each other, so they are never deallocated).
You can find fix the Memory Leaks using Analyze option of XCode
Open XCode --- Product --- Analyze
Then you can find the memory allocation issues locaton with blue identification.
You can fix them where you not using any object which are allocated and so on....
Hope it helps you..
Instruments can visualize retain cycles under ARC in a graphically interesting way. I also remember that a few days ago I spotted the "Cycles" view in Instruments by accident.
Now where I started using ARC, suddenly I'm not able to find that anymore. The Allocations and VM Tracker instruments don't offer it, and the Leaks instrument either.
What must I do in order to see retain cycles?
Found a screenshot as evidence:
Using Xcode 4.2.1, I found the it in "Leaks", under "Cycles & Roots". However, I've found it less than useful when using ARC. It does detect CF leaks and apparently I'm leaking a recursive block, which I can't do anything about, but I've had to root out several retain cycles that Leaks never found. For finding retain cycles, I recommend using "Allocations" and running several heap shots between performing the action you suspect of 'leaking'. You then then look through the interim heap shots to find the culprit.