1

Following is the code used by me. With this code deinit is not called, but if I comment out this line weakSelf?.tableView.reloadData() from code deinit gets called. Am I doing something wrong?

ZLNetworkHelper.sharedManager.getUserSavedAddress { (response) in
        print("getUserSavedAddressFinished")
        ZLProgressIndicator.stopAnimation()
        if response.isSuccess && response.value != nil {

            weak var weakSelf = self
            guard weakSelf != nil else {
                return
            }

            weakSelf!.address = response.value!.sorted(by: {$0.isDefault && !$1.isDefault})
            weakSelf!.isExistingAddressSectionExpanded = false

            if weakSelf!.address.count == 0 {
                weakSelf!.title  = LocalizationUtility.RCLocalizedString("ADD_ADDRESS")
            }

            DispatchQueue.main.async {
                weakSelf!.tableView.reloadData()
            }
            if completion != nil {
                completion!(true)
            }
        }
        else {

            let message = response.error?.localizedDescription
            ZLCustomAlertVC.presentAlertInVC(self, withErrorMessage:message)
        }
    }
Ajay Kumar
  • 1,807
  • 18
  • 27
  • I know you did use `guard`, but FWIW since it's an async call, your force unwrapping could still crash! See [this](https://stackoverflow.com/questions/45327236/is-it-safe-to-force-unwrap-variables-that-have-been-optionally-accessed-in-the-s/45329642#comment77621183_45329642) comment and the entire answer – mfaani Oct 01 '17 at 13:27
  • @Honey Thanks for this info, really helpful. – Ajay Kumar Oct 01 '17 at 13:34

2 Answers2

1

You want to capture self weakly in the closure like:

getUserSavedAddress { [weak self] (response) in

When you capture it later, you're still grabbing a reference to self in the closure.

Try the implementation like this:

ZLNetworkHelper.sharedManager.getUserSavedAddress { [weak self] (response) in
    DispatchQueue.main.async {
        print("getUserSavedAddressFinished")
        ZLProgressIndicator.stopAnimation()
        if response.isSuccess && response.value != nil {


           self?.address = response.value!.sorted(by: {$0.isDefault && !$1.isDefault})
            self?.isExistingAddressSectionExpanded = false

            if self?.address.count == 0 {
                self?.title  = LocalizationUtility.RCLocalizedString("ADD_ADDRESS")
            }

                self?.tableView.reloadData()
            if completion != nil {
                completion!(true)
            }
        }
        else {

            let message = response.error?.localizedDescription
            ZLCustomAlertVC.presentAlertInVC(self, withErrorMessage:message)
        }
    }   
}

(I've only updated this on SO, so you may need to unwrap, etc. as needed)

Fred Faust
  • 6,696
  • 4
  • 32
  • 55
  • I made this change then also Deinit is not called – Ajay Kumar Oct 01 '17 at 13:23
  • I have exactly used what you have written in the answer still, deinit is not called. If I remove tableViewReloadData() deinit gets called. – Ajay Kumar Oct 01 '17 at 13:33
  • Inside tableView CellforRowAtIndexPath method I am setting a delegate like this **cell.delegate = self**, If I remove this line then Deinit gets called, How should I handle this? – Ajay Kumar Oct 01 '17 at 13:52
  • @AjayKumar that's a different situation, the cell's delegate should be defined as a weak var, like: 'weak var delegate: DelgateType?' – Fred Faust Oct 01 '17 at 14:00
  • My bad, the problem was this, delegate var was not weak in the cell, Now everything works properly, And if I use the original code which I posted in question that way of using the weak self also works fine. – Ajay Kumar Oct 01 '17 at 14:21
0

You can use the code given by Fred Faust but use weakself in the else part also where you present the alert.

Sreehari
  • 1
  • 1