Search code examples
iosswiftxcodeuikitcocoapods

Custom Delegate function not called befor UIAlertController SubClass Dismiss


I Created a subclass of UIAlertController which do some stuff but befor dimissing it i call Delegate (is a custom protocol for delegation pattern to use this in UIViewController) right befor dimiss statement

  • Inserted this Code in my Custom Alert Class.
  • I have a strong reference from it in UIViewController and set delegate to self.
  • Conforming protocol and set a break point never reached during runtime.
// this code in my custom subClass of UIAlertController 

   func addRequestAction() {
        addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak self] _ in
            self?.checkConnection { isConnected in
                print("xxxxxxxxx", isConnected)
                DispatchQueue.main.async {
                    if isConnected {
                        self?.delegate?.didConnect() // here i call delegate function but never executed
                        self?.dismiss(animated: true, completion: nil)
                    } else {
                        let alert = NetworkCheckerAlert(self?.delegate)
                        self?.dismiss(animated: true, completion:nil)
                        guard let viewController = UIApplication.shared.keyWindow?.rootViewController else { return }
                        viewController.present(alert, animated: true, completion: nil)
                    }
                }
            }
        }))
    }

Solution

  • Removing [weak self] should solve the problem:

    addAction(UIAlertAction(title: "OK", style: .default, handler: { /*[weak self]*/ _ in
    

    Normally in a view controller, using [weak self] is fine because the self refers to the VC, but here self refers to the UIAlertController.

    I'm assuming you are not retaining the reference to your custom alert controller when you are presenting it (i.e. you just declare it as a local variable, present it, and throw it away).

    Now let’s consider what happens when the DispatchQueue closure is run. At this point, the alert has already been dismissed, so “the screen” is not retaining a reference to it. Since nothing is retaining a strong reference to the alert controller (only a weak reference from the closure exists), The instance of UIAlertController subclass is deallocated.

    This is just a guess though. You can do more investigation by seeing which objects are in memory, and who are holding a reference to whom using the method described here (written by me).