简体   繁体   中英

CNContactViewControllerDelegate not called when using the Coordinator pattern in SwiftUI

I've been grinding on this issue for quite a few days now and it seems like SwiftUI's relative "newness" doesn't seem to help me with this.

My gut feeling is that I'm somehow using CNContactViewControllerDelegate wrong but both Apple's documentation as well as other questions on SO make it seem like it should work. Maybe, it is also caused by .sheet 's handling, but I wasn't able to isolate the issue as well. Not wrapping NewContactView inside NavigationView also made no difference and removed the default navigation bar (as expected).

I'm showing the CNContactViewController with init(forNewContact:) to give the app's users an ability to add new contacts. Persisting and everything works fine, however, none of the delegate's functions seem to get called.

Neither dismissing the modal with the "swipe to dismiss" gesture introduced in iOS 13 calls the delegate function, nor using the navigation buttons provided by CNContactViewController .

import Foundation
import SwiftUI
import ContactsUI

struct NewContactView: UIViewControllerRepresentable {
    class Coordinator: NSObject, CNContactViewControllerDelegate, UINavigationControllerDelegate {

        func contactViewController(_ viewController: CNContactViewController, didCompleteWith contact: CNContact?) {
            if let c = contact {
                self.parent.contact = c
            }
            viewController.dismiss(animated: true)
        }
        
        func contactViewController(_ viewController: CNContactViewController, shouldPerformDefaultActionFor property: CNContactProperty) -> Bool {
            return true
        }

        var parent: NewContactView

        init(_ parent: NewContactView) {
            self.parent = parent
        }
    }

    @Binding var contact: CNContact

    init(contact: Binding<CNContact>) {
        self._contact = contact
    }

    typealias UIViewControllerType = CNContactViewController

    func makeCoordinator() -> Coordinator {
        return Coordinator(self)
    }

    func makeUIViewController(context: UIViewControllerRepresentableContext<NewContactView>) -> NewContactView.UIViewControllerType {
        let vc = CNContactViewController(forNewContact: CNContact())
        vc.delegate = makeCoordinator()
        return vc
    }

    func updateUIViewController(_ uiViewController: NewContactView.UIViewControllerType, context: UIViewControllerRepresentableContext<NewContactView>) {
    }
}

The view's code for showing the controller looks like this:

.sheet(isPresented: self.$viewModel.showNewContact, onDismiss: { self.viewModel.fetchContacts() }) {
        NavigationView() {
                NewContactView(contact: self.$viewModel.newContact)
        }
}

Thank you for any pointers. Rubberducking sadly didn't help...

SwiftUI creates coordinator by itself and provides it to representable in context, so just use

    func makeUIViewController(context: UIViewControllerRepresentableContext<NewContactView>) -> NewContactView.UIViewControllerType {
        let vc = CNContactViewController(forNewContact: CNContact())
        vc.delegate = context.coordinator      // << here !!
        return vc
    }

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