2

I have an app I am developing and it definitely is having some memory issues after extended use on the iPad mini 1. The debugger will start spitting out memory warnings until it crashes and I would like to know what controller in our code is causing this problem.

Here is an example of the debug message.

2015-03-11 17:04:02.420 PROJECT_NAME[154:4100] Received memory warning.

The Debug message I get gives a timestamp and the Project Name with some info in brackets. How can I use this to find what controller is causing this problem? The bracket info doesn't seem to be code line numbers since the name before it is the project name not a file name.

The other alternative I've been thinking is possibly putting a print statement in the controllers didRecieveMemoryWarning() function.

What is the best to track down and debug these in Swift?

Let me know if I need to provide more info.

UPDATE

I am also curious to know about some of the common causes for memory leaks in Swift? In my case I am using a UITableView that navigates through a navigation controller to another UITableView. The second table view contains some custom cells which use mainly texts and small images. I'm assuming that the images (although small and mainly for asthetic purposes) are whats causing the issue. I'm going to use instruments as suggested next to debug this to find out exactly what is doing this.

UPDATE

So I've been playing in the profiler trying to find things that could be causing memory leaks, and allot of the things in the profiler seem to be code that is library code, but I did after some sifting find some references to stuff that was in my code. One consistently was repeated being the following.

enter image description here

This code is inside the a custom UITableViewCell awake from Nib method, and has to do with setting the initial state of an image that will change depending on the state of the data that belongs to that cell. I'm guessing that this dynamic image loading could be causing one of these problems. The question is, what do I do to fix it?

Unome
  • 6,750
  • 7
  • 45
  • 87
  • 1
    You can use instruments tool – Javier Flores Font Mar 11 '15 at 23:29
  • 1
    The Allocations profiler can help. So can the time profiler, if the memory issues are causing your app to respond slowly. – Aaron Brager Mar 11 '15 at 23:29
  • 2
    There are tons of completely different issues that could cause memory problems. Common issues include strong reference cycles, abandoned memory, and poor cache usage. You should identify _what_ is leaking (using Instruments), and that will help you narrow down the candidate issues. – Rob Mar 12 '15 at 04:34
  • 1
    @Rob, I added to the question some more detailed info including some info I found in the profiler. – Unome Mar 12 '15 at 22:48
  • 1
    Great, you've used Instruments to identify what's leaking, the question is now _why._ I'd check to see if the view controller, on whose view these buttons appear, is released. if not, you might have a strong reference cycle (e.g. repeating `NSTimer` or some block property that references self. So, first confirm if the view controller, itself is leaking, and then figure out why (starting with what strong references to it exist). If it's not apparent looking at the code, Instruments has a feature to track retain counts which you can use to identify where the strong references are made. – Rob Mar 12 '15 at 23:17
  • So I'm finding the memory issues pretty easy here in Instruments, but where in Instruments does it let me by controller view releases? – Unome Mar 12 '15 at 23:46
  • You can select a range to examine in the allocations graph and it will show you everything allocated and not released. So run the app, selecting the range before the vc is presented thru after its dismissal, look at the allocations, and see if your vc is still there, unreleased. If so, if you run allocations with "record reference counts", you can then drill into that undeallocated object in Allocations tool and see all of the individual retains and releases. See latter part of http://stackoverflow.com/a/14105056/1271826. – Rob Mar 13 '15 at 04:33

1 Answers1

6

At this point, you need to change gears if you want to identify the source of your memory problems. Use Instruments as illustrated in WWDC 2013 video Fixing Memory Issues or WWDC 2012 iOS App Performance: Memory. Using Allocations tool in Instruments you can identify what is being allocated and not being released. Only then can you proceed to resolving the issue (e.g. fixing any strong reference cycles, etc.). We can't advise you how to remedy the problem until you identify the source of the problem, and Instruments will help you do that.

While those presentations illustrate the practice with Objective-C, the principles are the same in Swift, and the use of the Allocations and Leaks tools in Instruments is the same.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • 1
    I'll check those out and update the post or accept depending on how it goes. +1 Question, what does [NUMBER: NUMBER] mean in the print out from the debugger mean? – Unome Mar 12 '15 at 03:30
  • 2
    I'm not entirely sure, but I don't think it matters. You really don't care where a memory warning was triggered, because it's invariably a result of memory problems that your app suffered from _in the past._ That's why you use something like Instruments because it's tracking the historical allocations, not just what's happening right now. The aforementioned video includes demonstrations of the right techniques for tracking down these sorts of issues. – Rob Mar 12 '15 at 03:43
  • 1
    I'll look at those tomorrow at work. What is the point of the didReceiveMemory warning function? I assume when it detects a problem it calls the contents of said method, and you can do some routine cleanup to decrease some memory usage, but if it only happens on past issues does that mean it calls every *didRecieveMemory* function from every controller since technically it is blind to what is causing the issue? – Unome Mar 12 '15 at 04:19
  • 2
    The point of `didReceiveMemoryWarning` is to give your app a chance to discard anything held in memory that it could otherwise easily recreate. For example, you might be cacheing images as you scroll through a table for performance reasons, but if you get a memory warning, you'd empty your cache. And, yes, it calls `didReceiveMemoryWarning` on every view controller (as well as post a notification that any object can observe, if it wants). It's a blunt instrument: The idea is "we're catastrophically short in memory, so get rid of anything you don't need." – Rob Mar 12 '15 at 04:40