0

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)
                    }
                }
            }
        }))
    }
M Ohamed Zead
  • 197
  • 10
  • What it tells when attempting to debug? Adding a breakpoint in the `handler` closure leads to...? – Ahmad F Mar 31 '20 at 20:19
  • Maybe it's because of the `[weak self]`? Does `xxxxxxxxx` get printed? Does `checkConnection` get called? – Sweeper Mar 31 '20 at 20:20
  • Could you please check `self` and `delegate` at the `self?.delegate?.didConnect()` line? I think you are having this issue since the `delegate` is `nil` here. If you like to add your delegate configuration code samples into your question I want to solve the issue with you. – emrcftci Mar 31 '20 at 20:25
  • in the debugger self is nil when I put checkpoint at print("xxxxx)@AhmadF – M Ohamed Zead Mar 31 '20 at 20:37
  • but could any one explain to me why self is nil while alert not dismissed yet ?? @Sweeper – M Ohamed Zead Mar 31 '20 at 20:39
  • We don't actually know that `self` is nil. It could be that `checkConnection` is not called at all. I asked those questions because they are the things that I would check in such a situation. Please answer them. – Sweeper Mar 31 '20 at 20:42
  • no checkConnection is called and isConnected is just a Bool value to indicate whether I am connected to internet or not if i turn wifi on or off get into if and else blocks so code is correct and the problem solved when i removed [weak self] but i don't know why ? and thanks in advence @Sweeper – M Ohamed Zead Mar 31 '20 at 20:50

1 Answers1

1

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).

Sweeper
  • 213,210
  • 22
  • 193
  • 313