简体   繁体   中英

Memory leak with swift object used from ObjC

I have a swift object that is instantiated from and Objective C class that does not use ARC. It is instantiated from the init and in the dealloc method is release it (it's stored in a @property so I send release to it's backing variable). However in the memory graph I see that whenever I instantiate this object (it's used whenever a users accesses a screen in the app) it never gets released. It just appears as a lone object in the memory graph. I saw that inside it it was creating a retain cycle in a closure but I made it weak there yet the problem persists. Any suggestions on how to further debug this issue?

The only coulprit I could think of was this closure, but it uses weak self now, yet the leak persists:

var observerToken : NSObjectProtocol?

@objc public override init() {
    self.accessToken = ""

    super.init()
    RPScreenRecorder.shared().delegate = self

    if #available(iOS 12.0, *) {
        self.observerToken = NotificationCenter.default.addObserver(forName: UIScreen.capturedDidChangeNotification, object: UIScreen.main, queue: OperationQueue.main) { [weak self] (notification)  in

            guard let strongSelf = self else { return }
            if strongSelf.broadcastPickerView != nil && strongSelf.screenTrack == nil {
                let isCaptured = UIScreen.main.isCaptured

                strongSelf.updateScreenSharingIcon(screenIsShared: isCaptured)
            }
        }
    }
}

If the graph is showing this object without any strong references (ie no arrow pointing to it), the problem is probably not this Swift code, but rather the manual reference counting in the Objective-C code.

There are a few things you can do to diagnose this:

  1. Use the static analyzer ( shift + command + B or “Product” » “Analyze”), which is surprisingly good at analyzing the memory use patterns in Objective-C manual retain counting code.

  2. Often the malloc stack feature can be helpful ( command + < or “Product” » “Scheme” » “Edit Scheme...” and then go to “Run” » “Diagnostics” and check “Malloc Stack”). If you do this, then the debug graph will also show you precisely where the object was instantiated (in case there might be some confusion about where the object was instantiated.)

  3. The “Allocations” tool in Instruments can show you the full malloc/retain/release history of the object. So fire up Instruments ( command + i or “Product Profile”), choose the “Leaks” instrument (which brings in the “Allocations” tool, too), start recording, exercise the app, stop recording, and now you can analyze the allocations related to this object. For example, if the Object was called Foo , you'd search for that in the search bar at the bottom of the screen. When you find Foo allocations, you can tap the little arrow next to it:

    在此处输入图片说明

    That will show you the list of allocations for that type, and you can again click on the little arrow next to the memory address to see the details:

    在此处输入图片说明

    That shows you every allocation, retain, and release. From that, you can diagnose where the additional retain or where the missing release is.

    In my example, I can see that I created it in viewDidLoad , that Foo did its own balanced retain and release , but that there is no final release in dealloc . Your scenario will likely be different, but this shows how you can diagnose what's going on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM