How to find the real cause of memory warning and how to resolve in iOS app

两盒软妹~` 提交于 2019-12-05 01:13:01

In WWDC 2012 Session 242 iOS App Performance: Memory,Apple introduce a way to detect memory problem with Allocations template of Instruments,start from 31 minutes.

1.


Apple suggests push pop repeatedly before take a snapshot of the heap,I prefer push pop just once.

The Snapshot button is Named "Mark Generation"

You should take Snapshot multiple times.

2.

If your memory grow between each Snapshot,You can dig into one of the snapshot except the first one.

Sort the objects by Persitent,you probably has seen your problem ViewController (if you only push pop once).Or you can just search for it.

3.Now you can dig into the call tree ,find and fix the problems.

4.You can use this technique not just for push pop viewControllers,but also scrolling in a tableView ,perform a databaseSearch and any other cases.

Try Infer it may helpfull, it reports memory leak problems in iOS and C code.

A static analyzer in deployment at Facebook, where it is used as part of the development process for mobile apps. Infer targets critical bugs such as null pointer exceptions, resource leaks and memory leaks — problems which lead to crashes or performance degradation in apps.

It looks like some object in your app is not being released, probably due to a retain cycle. Check all references to delegates are weak references. Also check blocks and ensure a strong reference to self is not captured in a block. If Object A keeps a strong reference to Object B, then passes a block containing a strong reference to self to object B, both objects are potentially locked in a retain cycle. Use this syntax to pass a weak reference to self:

 __weak typeof(self)weakSelf = self;

[doSomethingWithBlock:^() {
    __strong typeof(weakSelf)strongSelf = weakSelf;
    if (!strongSelf) {
        return;
    }
    [strongSelf doSomething];}];

in Swift do this:

someObject.doSomething() { [weak self] in
                    self?.doSomething()
                }

or use [unowned self] - both create a weak reference to self, in the case of [weak self], self is optional

To ensure all your objects are deallocated as expected, put a log statement in your dealloc / deinit functions and check they are really being called.

Wolverine,

Not saying this is an absolute answer to your question, but might provide you some hint to resolve the problem.

My Case :

Today morning while debugging the memory crash just as your's in one of my chat application I came accross a similar scenario. I am using SDWebImage as well to cache and load the images for the subsequent usages.

Initial observations made me believe that it is the crash because of SDWebImage. Soon I realized that crach was rather because of a very simple issue.

I had never tested whether my viewController's dealloc is getting called or not. On putting a breakpoint in dealloc I realized dealloc was never being called (for various reasons which I resolved now).

As in your case, my chatViewController though not loading 100's of images used to load 8 - 10 images at a time and crash started appearing when I used panorama images rather then normal Images.

Conclusion :

  1. My viewController had strong reference to UIImageView which was loading heavy images and as dealloc was never called for my ViewController all the loaded images were never realesed which resulted in memory crash.

  2. As I was loading heavy images I was performing several calculations to reduce the size of image. Most of the calculations involved repeated creation of image from NSData using UIImageJPEGRepresentation. Repeated allocation of data and image holder variable added to memory consumption of the app.

  3. As my ViewController involved number of API calls, I had created a singleton reference service class to which I used to pass complitionblocks and unknwingly I had used self inside the completionblocks passed to the methods. Which actually contributed to ARC reference count increment and never let my view controller to get deallocate.

Way to Debug

  1. As you have already mentioned in your question that you are loading loads of images in your ViewController make sure the viewController gets deallocated properly and releases all the memory loaded by all the ImageView's present in ViewController.

  2. If your ViewController's dealloc is not getting called then as just a way to test (remember not a solution) in viewWillAppear set all the imageView's image property to nil and forcefully clear the memory loaded.

  3. If ViewController dealloc not getting called turns out to be the culprit, try finding where you are sending self as strong reference. If found try using weak self.

I know its not a absolute answer to your question. Just sharing my experience with you. Hope this will atleast give you hint to solve yours.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!