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