代码之家  ›  专栏  ›  技术社区  ›  PaFi

代表保留圈虽然使用了弱

  •  0
  • PaFi  · 技术社区  · 7 年前

    协调员:

    class JournalDetailCoordinator: Coordinator {
        var dependencys: AppDependency
        var navigationController: UINavigationController
        var collectionViewController: CollectionViewWithMenuController!
        var imagePickerManager: ImagePickerManager!
    
    
    
    
        init(dependencys: AppDependency, navigationController: UINavigationController) {
            self.dependencys = dependencys
            self.navigationController = navigationController
    
        }
    
        func start() {
            loadCollectionViewController()
        }
    
        deinit {
            print("JournalDetailCoordinator deinitialisiert")
    
        }
    
        func loadCollectionViewController() {
            var journalDetailViewControllerContainer = [JournalDetailViewController]()
            for journal in dependencys.journals {
                let vc: JournalDetailViewController = dependencys.getJournalDetailDependency().createVC()
                vc.entryJournal = journal
                vc.delegateLoadImagePickerManager = self
                journalDetailViewControllerContainer.append(vc)
            }
            collectionViewController = dependencys.getCollectionViewWithMenuDependency().createVC()
            collectionViewController.managedViewControllers = journalDetailViewControllerContainer
            navigationController.pushViewController(collectionViewController, animated: true)
        }
    
    
    
    }
    
    extension JournalDetailCoordinator: LoadImagePickerManager {
        func loadImagePickerManager<T>(vc: T) where T : UIViewController & ImageGetterDelegate {
            imagePickerManager = ImagePickerManager()
            imagePickerManager.delegate = vc
            imagePickerManager.pickImage(viewController: collectionViewController)
    
        }
    }
    

    class JournalDetailViewController: UIViewController {
        lazy var mainView: JournalDetailViewP = {
            let view = JournalDetailViewP()
            return view
        }()
    
        typealias myType = SetJournal & HasImagePickerManager
        // dependency
        var dep: myType!
        var entryJournal: Journaling!
    
    
    
        var tableViewDataSource: JournalDetailTVDataSource?
        var collectionViewInteraction: AddImageCollectionViewInteraction?
    
        weak var delegateLoadImagePickerManager: LoadImagePickerManager?
    
        override func viewDidLoad() {
            super.viewDidLoad()
            title = "Detail Journal"
            // only for testing without coordinator connection
            //        if entryJournal == nil {
            //            entryJournal = NewJournal()
            //        }
            //        dep = AppDependency()
            setMainView()
            loadTableView()
            loadCollectionView()
    
        }
        override func viewDidDisappear(_ animated: Bool) {
            print("view did disappear Journal Detail")
        }
    
        deinit {
            dep.setJournal(newJournal: entryJournal)
            print("JournalDetailViewController deinitialisiert")
        }
    
    
        @objc func getImage() {
            delegateLoadImagePickerManager?.loadImagePickerManager(vc: self)
            //        dep.imagePickerManager.delegate = self
            //        dep.imagePickerManager.pickImage(viewController: self)
    
        }
    
        func saveEntry() {
    
        }
    
    }
    
    extension JournalDetailViewController: Storyboarded {}
    extension JournalDetailViewController: DependencyInjectionVC {}
    extension JournalDetailViewController: SetMainView {}
    
    extension JournalDetailViewController: ImageGetterDelegate {
        func returnImage(image: UIImage) {
            if entryJournal.image[0] ==  nil {
                entryJournal.image[0] = image
            } else {
                entryJournal.image.append(image)
            }
    
            loadCollectionView()
        }
    }
    
    extension JournalDetailViewController: AddImageCollectionViewInteractionDelegate {
        func deleteImage(index: Int) {
        }
    
        func addImage() {
            getImage()
        }
    }
    

    如果我不执行getImage()函数,它们就是释放,所以我认为这就是保留周期的原因。

    这是ImagePickerManager:

    protocol ImageGetterDelegate: class {
        func returnImage(image: UIImage)
    }
    
    class ImagePickerManager: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        var imagePicker = UIImagePickerController()
        weak var delegate: ImageGetterDelegate?
    
        override init() {
            super.init()
            print("ImagePickerManager initialisiert")
        }
    
    
        deinit {
            print("imagePickerManager deinitialisiert")
        }
        /// use to pick the Image, make sure to use the root ViewController to pass in to
        func pickImage<T:UIViewController>(viewController: T) {
            let alertList = UIAlertController(title: NSLocalizedString("Load Picture", comment: "Picture alert Alertcontroller"), message: nil, preferredStyle: .actionSheet)
    
            let cameraAction = UIAlertAction(title: "Camera", style: .default) {
                UIAlertAction in self.openCamera(viewController: viewController)
                alertList.dismiss(animated: true, completion: nil)
            }
    
            let galleryAction = UIAlertAction(title: "Gallery", style: .default) {
                UIAlertAction in self.openGallery(viewController: viewController)
                alertList.dismiss(animated: true, completion: nil)
            }
    
            let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) {
                UIAlertAction in
                alertList.dismiss(animated: true, completion: nil)
            }
    
            alertList.addAction(cameraAction)
            alertList.addAction(galleryAction)
            alertList.addAction(cancelAction)
    
            viewController.present(alertList, animated: true, completion: nil)
        }
    
        private func openCamera<T:UIViewController>(viewController: T) {
    
            if(UIImagePickerController .isSourceTypeAvailable(.camera)) {
                imagePicker.sourceType = .camera
                imagePicker.delegate = self
                viewController.present(imagePicker, animated: true, completion: nil)
            } else {
                let warningAlert = UIAlertController(title: "Warning", message: "You do not have a camera", preferredStyle: .alert)
                let cancelAction = UIAlertAction(title: "Okay", style: .cancel) {
                    UIAlertAction in
                    warningAlert.dismiss(animated: true, completion: nil)
                }
                warningAlert.addAction(cancelAction)
                viewController.present(warningAlert, animated: true, completion: nil)
            }
    
        }
    
        private func openGallery<T:UIViewController>(viewController: T) {
            imagePicker.sourceType = .photoLibrary
            imagePicker.delegate = self
            viewController.present(imagePicker, animated: true, completion: nil)
        }
    
        @objc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            picker.dismiss(animated: true, completion: nil)
            guard let image = info[.originalImage] as? UIImage else {
                print("Expected a dictionary containing an image, but was provided the following: \(info)")
                return
            }
            delegate?.returnImage(image: image)
    
        }
    
    }
    

    取消分配协调器后,ImagePickerManager未进行分配。所以我认为保留周期是因为我将viewvocontroller传递回LoadImagePickerManager中的协调器,然后将vc设置为协调器?有人知道怎么解决那个问题或者怎么做吗?

    LoadImagePickerManager:

    protocol LoadImagePickerManager: class {
        func loadImagePickerManager<T: UIViewController & ImageGetterDelegate>(vc: T)
    }
    

    imagePickerManager.pickImage(viewController: collectionViewController)
    

    因为我做了一些测试,如果我不执行这个部分,那么一切都很好。

    更新的ImagePickerManager类:

    class ImagePickerManager: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        var imagePicker = UIImagePickerController()
        weak var delegate: ImageGetterDelegate?
        var viewController: UIViewController!
    
        override init() {
            super.init()
            print("ImagePickerManager initialisiert")
        }
    
    
        deinit {
            print("imagePickerManager deinitialisiert")
        }
        /// use to pick the Image, make sure to use the root ViewController to pass in to
        func pickImage<T:UIViewController>(viewController: T) {
            self.viewController = viewController
            let alertList = UIAlertController(title: NSLocalizedString("Load Picture", comment: "Picture alert Alertcontroller"), message: nil, preferredStyle: .actionSheet)
    
            let cameraAction = UIAlertAction(title: "Camera", style: .default) {
                UIAlertAction in self.openCamera()
                alertList.dismiss(animated: true, completion: nil)
            }
    
            let galleryAction = UIAlertAction(title: "Gallery", style: .default) {
                UIAlertAction in self.openGallery()
                alertList.dismiss(animated: true, completion: nil)
            }
    
            let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) {
                UIAlertAction in
                alertList.dismiss(animated: true, completion: nil)
            }
    
            alertList.addAction(cameraAction)
            alertList.addAction(galleryAction)
            alertList.addAction(cancelAction)
    
            viewController.present(alertList, animated: true, completion: nil)
        }
    
        private func openCamera() {
    
            if(UIImagePickerController .isSourceTypeAvailable(.camera)) {
                imagePicker.sourceType = .camera
                imagePicker.delegate = self
                viewController.present(imagePicker, animated: true, completion: nil)
            } else {
                let warningAlert = UIAlertController(title: "Warning", message: "You do not have a camera", preferredStyle: .alert)
                let cancelAction = UIAlertAction(title: "Okay", style: .cancel) {
                    UIAlertAction in
                    warningAlert.dismiss(animated: true, completion: nil)
                }
                warningAlert.addAction(cancelAction)
                viewController.present(warningAlert, animated: true, completion: nil)
            }
    
        }
    
        private func openGallery() {
            imagePicker.sourceType = .photoLibrary
            imagePicker.delegate = self
            viewController.present(imagePicker, animated: true, completion: nil)
        }
    
        @objc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            picker.dismiss(animated: true, completion: nil)
            guard let image = info[.originalImage] as? UIImage else {
                print("Expected a dictionary containing an image, but was provided the following: \(info)")
                return
            }
            viewController = nil
            delegate?.returnImage(image: image)
    
        }
    
    }
    

    我在类中添加了一个viewController变量,并通过pickImage()设置它,然后当选择图像时,我将变量设置为nil。然后UIViewController被释放,但类ImagePickerManager仍然保持活动状态,并且没有被分配。

    0 回复  |  直到 7 年前
        1
  •  0
  •   Shubham Mishra    7 年前

    因为您使用的是弱委托,所以它决不会创建保留循环。

    尝试从导航堆栈中删除所有viewControllers,然后释放块将正常工作。

    返回homeViewController时,请根据您的要求(显示/推送)尝试以下代码:

    self.navigationController?.popToRootViewController(animated: true)
    
    self.view.window?.rootViewController?.dismiss(animated: true, completion: nil)
    

    编辑:

    确保您的协议是类类型,那么只有弱引用才能工作。

    protocol LoadImagePickerManager: class {
    
    }
    

    self.view.window?.rootViewController?.dismiss(animated: false, completion: nil)