TableView with SearchController - DEINIT not called

自闭症网瘾萝莉.ら 提交于 2019-11-30 14:54:29

Deleted my old answer, found the problem.

Remove:

definesPresentationContext = true // Remove this line...

Read about it here:

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/#//apple_ref/occ/instp/UIViewController/definesPresentationContext


There must a bug in UISearchController. Some Apple code must be retaining your controller.

Maybe the transition view (animation) is not completed when the controller is unlinked (it has special toView and fromView etc, that we can not reach), and this prevents the controller from being deallocated.

I think you should file this as a bug with Apple.


Also I would recommend changing your deinit to:

deinit {
  print("TBVC Dealloc")
  if let superView = searchController.view.superview
  {
    superView.removeFromSuperview()
  }
}

This will ensure the search controller is never trying to present stuff when getting deallocated, as this creates warnings and potential unexpected behavior.

I ran into this issue today as well this line of code seems to work to get your class released

  override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    searchController?.dismissViewControllerAnimated(false, completion: nil)
  }

Here is my sample project on dropbox https://www.dropbox.com/s/zzs0m4n9maxd2u5/TestSearch.zip?dl=0

I think the problem is that you are creating strong reference cycles between your closures and self, because you are using an unwrapped weak self in the closures.

For example, this:

if let safeSelf = weakSelf {
    appDel.backgroundThread(background: {
            let airportHelper = AirportHelper()
            safeSelf.airportData = airportHelper.getAirportSearchData()
        },
        completion: {
            dispatch_async(dispatch_get_main_queue()) {
                if safeSelf.isVisible && safeSelf.isTopViewController {
                    safeSelf.filteredData = (safeSelf.airportData)
                    safeSelf.loadingHud.removeFromSuperview()
                    safeSelf.tableView.reloadData()
                }
            }
    });
}

Should be:

appDel.backgroundThread(background: { [weak self] in
        let airportHelper = AirportHelper()
        self?.airportData = airportHelper.getAirportSearchData()
    },
    completion: {
        dispatch_async(dispatch_get_main_queue()) { [weak self] in
            if self?.isVisible && safeSelf.isTopViewController {
                self?.filteredData = (safeSelf.airportData)
                self?.loadingHud.removeFromSuperview()
                self?.tableView.reloadData()
            }
        }
});

You can also use [unowned self] and you won't have to treat them as optional, but to be honest, I forget the pros and cons of unowned vs. weak. But I'm confident that if you declare the weak self or unowned self in a capture list in the closure, rather than outside of the closure and unwrapping it, your object will be properly deinitialized.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!