iOS中在CNContactPicker的didSelect方法内无法弹出MFMessageComposeViewController?
Hey there! That error message you're seeing is super common when trying to present a new view controller right from the didSelect callback of CNContactPickerViewController—let me break down why it happens and how to fix it quickly.
Why the Error Occurs
The CNContactPickerViewController is a system-provided UI component. When you select a contact, the picker is in the middle of its dismissal transition (the "pre-commit handler" mentioned in the error). Core Animation has a restriction here: you can't add new view hierarchy changes (like presenting another VC) while the system is still wrapping up the picker's own transition animations. It's like trying to start a new task before the previous one has fully finished!
Solution 1: Delay the Present Operation (Simplest Fix)
The easiest way is to push your present call to the next run loop cycle using DispatchQueue.main.async. This gives the picker enough time to finish its dismissal before you present your message VC:
func contactPicker(_ picker: CNContactPickerViewController, didSelect contacts: [CNContact]) { // First, process your selected contact data here // (e.g., extract phone numbers/emails to pass to messageVC) // Delay the present until the picker's transition completes DispatchQueue.main.async { self.present(self.messageVC, animated: true, completion: nil) } }
Solution 2: Explicitly Dismiss the Picker First
If you want more control over the timing, you can explicitly dismiss the picker and present your VC in the dismissal completion block. This ensures the picker is fully gone before your message VC appears:
func contactPicker(_ picker: CNContactPickerViewController, didSelect contacts: [CNContact]) { // Process contact data first // Dismiss the picker, then present messageVC in the completion picker.dismiss(animated: true) { self.present(self.messageVC, animated: true, completion: nil) } }
Note: This works best if you presented the contact picker (the most common use case). If you pushed it onto a navigation stack, you'd use picker.navigationController?.popViewController(animated: true, completion: ...) instead.
Quick Check
Make sure your messageVC is properly initialized (not nil) and hasn't already been presented elsewhere—those issues can cause secondary problems, but the core error you're seeing is definitely about timing.
内容的提问来源于stack exchange,提问作者Marko

