0

I have a memory leak in when setting up an UIAlertController, I have seen other threads talking about memory leaks in UIAlertController. But I could not figure out how to change my code so the memory leak goes away. I changed itemSelected from a function to a computed property, but it did not change anything.

 protocol TriggerUIAlertController: class where Self: UIView {
        var itemsForPresenting: [String] { get }
        var titleForCancel: String { get }
        var titleForAlertController: String { get }
        var itemSelected: Int? {get set}
    }

    extension TriggerUIAlertController {

         func triggerUIAlerController() {
            let alertList = UIAlertController(title: titleForAlertController, message: nil, preferredStyle: .actionSheet)
            let closure = { (alert: UIAlertAction!) -> Void in
                let index = alertList.actions.index(of: alert)
                guard index != nil else {
                    return
                }

                ///produces memory leak, idk why though -> has to be checked
                self.itemSelected = index!
            }
            for x in itemsForPresenting {
                alertList.addAction(UIAlertAction(title: x, style: .default, handler: closure))
            }
            self.window?.rootViewController?.present(alertList,animated: true, completion: nil)
            let cancelAction = UIAlertAction(title: titleForCancel, style: .cancel, handler: nil)
            alertList.addAction(cancelAction)
        }
    }

Btw: Is it normal that instruments uses after a usage of around five minutes a total of 50gb ram?

Kaushik Makwana
  • 1,329
  • 2
  • 14
  • 24
PaFi
  • 888
  • 1
  • 9
  • 24

1 Answers1

1

It's not a leak caused by UIAlertController but more generally by a "retain cycle", you can have that with every closure that contains reference to self or any variable created outside the closure.

You can avoid it by changing the "definition" of the closure:

  let closure = { [weak self, weak alertList] (alert: UIAlertAction!) -> Void in
        guard let self = self, let alertList = alertList, let index = alertList.actions.index(of: alert) else { return }               
            self.itemSelected = index

You can find a more complete explanation here: Swift closures causing strong retain cycle with self

Code review: another implementation of the closure can be:

  let closure = { [weak self, weak alertList] alert in
        guard let self = self, let alertList = alertList, let index = alertList.actions.index(of: alert) else { 
            return
        }               
        self.itemSelected = index
  }
Renaud
  • 380
  • 4
  • 13