This seems to be specific to iOS 13.1, as it works as expected on iOS 13.0 and earlier versions to add a contact in CNContactViewController, if I 'Cancel', the action sheet is overlapping by keyboard. No actions getting performed and keyboard is not dismissing.
问题:
回答1:
I couldn't find a way to dismiss keyboard. But at least you can pop ViewController using my method.
- Don't know why but it's impossible to dismiss keyboard in CNContactViewController. I tried endEditing:, make new UITextField firstResponder and so on. Nothing worked.
- I tried to alter action for "Cancel" button. You can find this button in NavigationController stack, But it's action is changed every time you type something.
- Finally I used method swizzling. I couldn't find a way to dismiss keyboard as I mentioned earlier, but at least you can dismiss CNContactViewController when "Cancel" button is pressed.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
changeImplementation()
}
@IBAction func userPressedButton(_ sender: Any) {
let controller = CNContactViewController(forNewContact: nil)
controller.delegate = self
navigationController?.pushViewController(controller, animated: true)
}
@objc func popController() {
self.navigationController?.popViewController(animated: true)
}
func changeImplementation() {
let originalSelector = Selector("editCancel:")
let swizzledSelector = #selector(self.popController)
if let originalMethod = class_getInstanceMethod(object_getClass(CNContactViewController()), originalSelector),
let swizzledMethod = class_getInstanceMethod(object_getClass(CNContactViewController()), swizzledSelector) {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
}
PS: You can find additional info on reddit topic: https://www.reddit.com/r/swift/comments/dc9n3a/bug_with_cnviewcontroller_ios_131/
回答2:
Kudos to @GxocT for the the great workaround! Helped my users immensely.
But I wanted to share my code based on @GxocT solution hoping it will help others in this scenario.
I needed my CNContactViewControllerDelegate
contactViewController(_:didCompleteWith:)
to be called on cancel (as well as done).
Also my code was not in a UIViewController
so there is no self.navigationController
I also dont like using force unwraps when I can help it. I have been bitten in the past so I chained if let
s in the setup
Here's what I did:
Extend
CNContactViewController
and place the swizzle function in
there.In my case in the swizzle function just call the
CNContactViewControllerDelegate
delegate
contactViewController(_:didCompleteWith:)
withself
and
self.contact
object from the contact controllerIn the setup code, make sure the swizzleMethod call to
class_getInstanceMethod
specifies theCNContactViewController
class instead ofself
And the Swift code:
class MyClass: CNContactViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.changeImplementation()
}
func changeCancelImplementation() {
let originalSelector = Selector(("editCancel:"))
let swizzledSelector = #selector(CNContactViewController.cancelHack)
if let originalMethod = class_getInstanceMethod(object_getClass(CNContactViewController()), originalSelector),
let swizzledMethod = class_getInstanceMethod(object_getClass(CNContactViewController()), swizzledSelector) {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
func contactViewController(_ viewController: CNContactViewController, didCompleteWith contact: CNContact?) {
// dismiss the contacts controller as usual
viewController.dismiss(animated: true, completion: nil)
// do other stuff when your contact is canceled or saved
...
}
}
extension CNContactViewController {
@objc func cancelHack() {
self.delegate?.contactViewController?(self, didCompleteWith: self.contact)
}
}
The keyboard still shows momentarily but drops just after the Contacts controller dismisses.
Lets hope apple fixes this
回答3:
The user can in fact swipe down to dismiss the keyboard and then tap Cancel and see the action sheet. So this issue is regrettable and definitely a bug (and I have filed a bug report) but not fatal (though, to be sure, the workaround is not trivial for the user to discover).