Glitch while transitioning between view controllers

hey guys! I am using a custom transition animation to transition between view controllers. Here is the code


extension UIViewController {

func presentDetail(_ viewControllerToPresent: UIViewController) {

let transition = CATransition()

transition.duration = 0.3

transition.type = CATransitionType.push

transition.subtype = CATransitionSubtype.fromRight

transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)

self.view.window?.layer.add(transition, forKey: kCATransition)

present(viewControllerToPresent, animated: false, completion: nil)

}

func dismissDetail() {

let transition = CATransition()

transition.duration = 0.3

transition.type = CATransitionType.push

transition.subtype = CATransitionSubtype.fromLeft

self.view.window?.layer.add(transition, forKey: kCATransition)

dismiss(animated: false, completion: nil)

}


}


sometimes when I am transitioning to the new VC, the contents of the old VC shows up on the new VC for a split second and then refreshes. Can anyone please tell me why this is happening and how to fix this? This happens even on physical devices. The viewDidLoad() in the new VC does not do much either apart from calling a couple of functions.

Accepted Reply

You could change your design and use segues:


In didSelectRowAt

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        tableView.deselectRow(at: indexPath, animated: true) // NOT SURE THIS IS NEEDED
        selectedStudyMaterial = studyMaterialInstance[indexPath.row] // NOW it is set
        self.performSegue(withIdentifier: "SegueToDetail", sender: self)    // unwindFromVEToCalcViewController
  }


And prepare:


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
       
        if (segue.identifier == "SegueToDetail") && selectedStudyMaterial != nil {
            if let nextVC = segue.destination as? StudyMaterialInfoVC {
               nextVC.datainit(title: selectedStudyMaterial.title, contributor: selectedStudyMaterial.contributor, topics: selectedStudyMaterial.topic, downloadURL: selectedStudyMaterial.downloadURL, college: selectedStudyMaterial.college, uid: selectedStudyMaterial.uid)
               
            }
        }
    }

Replies

Could you show where and how you call presentDetail and dismissDetail

I am calling presentDetrail in didSelectRow of the previous VC. The problem exists only with presentDetails. Anyway, here is the code


func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

tableView.deselectRow(at: indexPath, animated: true)

let selectedStudyMaterial: StudyMaterial!

selectedStudyMaterial = studyMaterialInstance[indexPath.row]

let nextVC = storyboard?.instantiateViewController(withIdentifier: "SMIVC") as? StudyMaterialInfoVC

nextVC?.datainit(title: selectedStudyMaterial.title, contributor: selectedStudyMaterial.contributor, topics: selectedStudyMaterial.topic, downloadURL: selectedStudyMaterial.downloadURL, college: selectedStudyMaterial.college, uid: selectedStudyMaterial.uid)

presentDetail(nextVC!)

}


I really have no idea why this is happening. Please help me.


Thanks.

I tried introducing a delay of 0.1s in the previous VC before calling presentDetail and it worked properly. But that obviously is a bad way of coding. Given how powerful these devices are, it not suppose to be related to performance right? After all I am just initializing the display elements in ViewDidLoad().

Could you show your dataInit func ?

And show where you introcuced the delay exactly.

okay so 2 methods works:


1. Introduce delay in the previous VC DidSelectRow function (in the previous VC)

let timer = Timer.scheduledTimer(withTimeInterval: 10.0, repeats: false) { (timer) in

self.presentDetail(nextVC!)

}

This solved the probelm


2. I am using Swift Spinner cocoapods to show loading activity, so I called SwiftSpinner.show(to present the loading indicator) in the ViewDidLoad() of the new VC and hid it at the end of my displayinit() which is one of the function in called from ViewDidLoad(). This strangely solved the problem. The swiftspinner doesnt show as expected as the displayinit() will execute within no time and this solved the problem as well.


I am unable to understand these complexities.


This is the datainit() function

func datainit(title: String, contributor: String, topics: [String], downloadURL: String, college: String, uid: String){

Title = title

self.contributor = contributor

self.topics = topics

self.downloadURL = downloadURL

self.College = college

self.LUID = uid

}

You said:

sometimes when I am transitioning to the new VC, the contents of the old VC shows up on the new VC for a split second


what is this oldVC ? Is it a StudyMaterialInfoVC ?

StudyMaterialVC is the current VC(old) and StudyMaterialInfoVC is the new VC it is suppose to transition to. didSelectRow function is from StudyMaterialVC, which is where I added the delay. StudyMaterialInfoVC is the new controller and I have uploaded the datainit() of it as well. When I add a loading status cocoapod to the new VC(StudyMaterialInfoVC), there is not glitch. which is very wierd. I am extremely sorry for the confusion.

You could change your design and use segues:


In didSelectRowAt

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        tableView.deselectRow(at: indexPath, animated: true) // NOT SURE THIS IS NEEDED
        selectedStudyMaterial = studyMaterialInstance[indexPath.row] // NOW it is set
        self.performSegue(withIdentifier: "SegueToDetail", sender: self)    // unwindFromVEToCalcViewController
  }


And prepare:


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
       
        if (segue.identifier == "SegueToDetail") && selectedStudyMaterial != nil {
            if let nextVC = segue.destination as? StudyMaterialInfoVC {
               nextVC.datainit(title: selectedStudyMaterial.title, contributor: selectedStudyMaterial.contributor, topics: selectedStudyMaterial.topic, downloadURL: selectedStudyMaterial.downloadURL, college: selectedStudyMaterial.college, uid: selectedStudyMaterial.uid)
               
            }
        }
    }