简体   繁体   中英

Swift adding VC from inside a closure not working

So i'm trying to display a loading view when a user tap on a button. Below is the function

    /// Handles the shutter button tapped
    @objc func shutterTapped() {
        let parent = self.parent as! CameraActionViewController

        if parent.timerEngine.currentTime != 0 { parent.timerEngine.presentTimerDisplay() }
// This acts as a timer for the shutter to fire. (like a timer function for a camera)
        DispatchQueue.main.asyncAfter(deadline: .now() + Double(parent.timerEngine.currentTime)) {

            parent.cameraManager.capturePictureWithCompletion({ result in
                switch result {
                case .failure:
                    AlertHelper.shared.presentDefault(title: "Error", message: "Looks like there was an error capturing the image.", to: self)

                case .success(let content):
                    let loadingVC = LoadingViewController()
                    parent.parent!.addVC(loadingVC)
                    print("processing...")

                    if let image = content.asImage {
                        guard let editedImage = FilterEngine.shared.process(originalImage: image) else {
                            TapticHelper.shared.errorTaptic()
                            return
                        }

                        guard let data = editedImage.jpegData(compressionQuality: 1.0) else {
                            TapticHelper.shared.errorTaptic()
                            return
                        }

                        DataEngine.shared.save(imageData: data)
                        print("Success")
                        TapticHelper.shared.successTaptic()
                        loadingVC.removeVC()
                    }
                }
            })
        }
    }

When the camera successfully captures the image and start to edit with all the filters selected by the user, I want to display the loading view. Because this is a heavy task and will freeze the UI for a second.

let loadingVC = LoadingViewController()
parent.parent!.addVC(loadingVC)
...
loadingVC.removeVC()

The method to add is here:

    func addVC(_ child: UIViewController) {
        addChild(child)
        view.addSubview(child.view)
        child.didMove(toParent: self)
    }

    func removeVC() {
        guard parent != nil else { return }

        willMove(toParent: nil)
        view.removeFromSuperview()
        removeFromParent()
    }

But for some reason, it is not showing the view at all. I then found out that it is somehow executed after the DataEngine.shared.save(imageData: data) line (adding to VC). Therefore since it is adding and removing at the same time, it shows nothing.

Any help?

You need to Dispatch all UI related tasks to the main queue. Try:

DispatchQueue.main.async {
    parent.parent!.addVC(loadingVC)
}

And:

DispatchQueue.main.async {
    loadingVC.removeVC()
}

Or simply put everything in the main queue right after the background task is complete:

parent.cameraManager.capturePictureWithCompletion({ result in
    DispatchQueue.main.async {
        //...
    }
}

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