2

This is not a dupe of this question or this question because those answers didn't work.

For some reason, the cancel button has no effect when presenting a CNContactViewController inside a UINavigationController.

Steps to reproduce:

  1. Copy this view controller.
  2. Tap cancel button.

Expected behavior:

The CNContactViewController gets dismissed.

Actual behavior:

Nothing happens. Breakpoints inside the delegate function never get called.

import Foundation
import Contacts
import ContactsUI


class ContactViewController: UIViewController, CNContactViewControllerDelegate {


    override func viewDidLoad() {
        super.viewDidLoad()

        createContact()
    }


    func createContact() {
        let contactController = CNContactViewController(forNewContact: nil)

        contactController.delegate = self
        contactController.allowsEditing = true
        contactController.allowsActions = true
        contactController.title = ""
        contactController.view.layoutIfNeeded()

        let contactNavController = UINavigationController(rootViewController: contactController)
        contactNavController.navigationBar.backgroundColor = UIColor.red

        present(contactNavController, animated:true)
    }


    // =============================================================================================================
    // MARK: CNContactViewControllerDelegate Functions
    // =============================================================================================================
    func contactViewController(_ viewController: CNContactViewController, didCompleteWith contact: CNContact?) {
        viewController.dismiss(animated: true, completion: nil)
        dismiss(animated: true, completion: nil)
        print("hi")
    }


    func contactViewController(_ viewController: CNContactViewController, shouldPerformDefaultActionFor property: CNContactProperty) -> Bool {
        print("yo")
        return true
    }


    // =============================================================================================================
    // MARK: UIViewController Functions
    // =============================================================================================================
    override var prefersStatusBarHidden: Bool {
        return true
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
Crashalot
  • 33,605
  • 61
  • 269
  • 439
  • Did you try presenting the `CNContactViewController` directly instead putting it in a nav controller? – rmaddy Dec 04 '18 at 02:42
  • @rmaddy yes. if you do this, the view controller isn't even visible. some bug apparently. thanks for the reply! – Crashalot Dec 04 '18 at 02:43
  • 1
    Possible duplicate of [Unable to dismiss CNContactViewController](https://stackoverflow.com/questions/37390406/unable-to-dismiss-cncontactviewcontroller) – SPatel Dec 04 '18 at 04:36
  • @SPatel hi those solutions were tried as well. it's not a duplicate. will update the question to reflect this. thanks! – Crashalot Dec 04 '18 at 04:39
  • For me your code is working fine. In simulator I have tested. and I able to dismiss it with cancel button in red color nav bar. What I changed is added delay on view didload and then call createContact func – Prashant Tukadiya Dec 04 '18 at 05:01
  • In your code, `CNContactViewController` is the first and only in `UINavigationController.viewControllers`. I've only read the docs, and not tried this in real life, but the behavior of cancel seems problematic in this case. – benc Jul 25 '19 at 04:27

1 Answers1

2

I have tried your code right now; And cancel button dismiss view controller without problem. The problem in my case was about showing view controller which fixed by change the present of contactNavController to:

DispatchQueue.main.async {
            self.present(contactNavController, animated:true)
        }

try it, maybe you have thread problem

Fa.Shapouri
  • 988
  • 2
  • 12
  • 30