简体   繁体   中英

How to cache UIViewControllers for UICollectionViewCell use?

I have created a UICollectionView with cells containing several types of UIViewController views as their contentView. I would like to cache the UIViewController 's which are not in use. I have tried creating a dictionary of the currently used UIViewController 's based on their indexPath, and a set of unused UIViewController 's to to be recycled UIViewController 's. Im noticing however that my UIViewControllers are not being deinitialized. I've based my implementation on these answers Add UIViewController to UICollectionViewCell and Make PageViewController reuse viewControllers like tableView .

Below is my implementation

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        addViewController(toCell: cell, at: indexPath, of: viewTypes[indexPath.item])
    }

    func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        removeViewController(fromCell: cell, at: indexPath)
     //   cleanCachedViewControllers(index: indexPath.item)
    }

    func addViewController(toCell cell:UICollectionViewCell, at indexPath:IndexPath,of type:ViewControllerType){
        var childViewController:UIViewController!

        if let cvc = currentViewControllers[indexPath]{
            childViewController = cvc
        }else{
            childViewController = TestViewController()
            currentViewControllers[indexPath] = childViewController
        }
        self.addChild(childViewController)
        childViewController.view.frame = cell.contentView.bounds
        cell.contentView.addSubview(childViewController.view)
        childViewController.didMove(toParent: self)
    }

    func removeViewController(fromCell cell:UICollectionViewCell, at indexPath:IndexPath){
        guard let childViewController = currentViewControllers[indexPath] else {
            return
        }
        print("remove view controller called")
        childViewController.willMove(toParent: nil)
        childViewController.view.removeFromSuperview()
        childViewController.removeFromParent()
    //        currentViewControllers[indexPath] = nil
   //         currentViewControllers.removeValue(forKey: indexPath)
        childViewController.view = nil
        recycledViewControllers.insert(childViewController)
    } 

    func getRecycledViewController(type:ViewControllerType)->UIViewController{

        var unusedViewControllers = recycledViewControllers.filter { (viewController) -> Bool in
            return viewController.isKind(of: type.type) && viewController.parent == nil
        }

        if let reusableViewController = unusedViewControllers.first{
            recycledViewControllers.remove(reusableViewController)
            return reusableViewController
        }else{
            let newViewController = type.initializeViewController()
            //            recycledViewControllers.append(newViewController)
            return newViewController
        }
    }

You probably have a circular reference that is keeping your objects from deallocating.

Xcode 8 and higher allows you to debug and visualize the current memory graph. This is very useful to troubleshoot why an object is not being deallocated.

https://developer.apple.com/videos/play/wwdc2018/416/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM