这似乎是特定于iOS 13.1的,因为它可以在iOS 13.0和更早版本上按预期工作,可以在CNContactViewController中添加联系人,如果我单击“取消”,操作表会被键盘重叠。没有执行任何操作,也没有关闭键盘。
这似乎是特定于iOS 13.1的,因为它可以在iOS 13.0和更早版本上按预期工作,可以在CNContactViewController中添加联系人,如果我单击“取消”,操作表会被键盘重叠。没有执行任何操作,也没有关闭键盘。
Answers:
伟大的解决方法对@GxocT表示感谢!极大地帮助了我的用户。
但是我想基于@GxocT解决方案共享我的代码,希望它能在这种情况下对其他人有所帮助。
我需要CNContactViewControllerDelegate
contactViewController(_:didCompleteWith:)
在取消时调用我(以及完成)。
另外我的代码不在,UIViewController
所以没有self.navigationController
当我可以帮助时,我也不喜欢使用武力包装。我过去曾被咬过,所以我if let
在设置中串了
这是我所做的:
扩展CNContactViewController
并在
其中放置swizzle功能。
就我而言,在swizzle函数中,只需使用联系人控制器中的和对象调用
CNContactViewControllerDelegate
委托
contactViewController(_:didCompleteWith:)
self
self.contact
在设置代码中,请确保swizzleMethod调用
class_getInstanceMethod
指定了CNContactViewController
类而不是self
和Swift代码:
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)
}
}
键盘仍会暂时显示,但在Contacts控制器关闭后会立即落下。
希望苹果能解决这个问题
我找不到解散键盘的方法。但是至少您可以使用我的方法弹出ViewController。
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:您可以找到有关reddit主题的其他信息:https : //www.reddit.com/r/swift/comments/dc9n3a/bug_with_cnviewcontroller_ios_131/
感谢@Gxoct的出色工作。我认为这对于与他们合作的人来说是非常有用的问题和解答CNContactViewController
。我也有这个问题(到现在为止),但是在目标c中。我将上述Swift代码解释为目标c。
- (void)viewDidLoad {
[super viewDidLoad];
Class class = [CNContactViewController class];
SEL originalSelector = @selector(editCancel:);
SEL swizzledSelector = @selector(dismiss); // we will gonna access this method & redirect the delegate via this method
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
创建CNContactViewController
访问解雇的类别;
@implementation CNContactViewController (Test)
- (void) dismiss{
[self.delegate contactViewController:self didCompleteWithContact:self.contact];
}
@end
不太熟悉Swizzling的人,您可以尝试matt的这篇文章
谢谢@GxocT的解决方法,但是,此处发布的解决方案与您在Reddit上发布的解决方案不同。
Reddit上的那个对我有用,这个不起作用,所以我想在这里重新发布。与swizzledMethod的区别在于:
let swizzledMethod = class_getInstanceMethod(object_getClass(self), swizzledSelector) {
整个更新的代码是:
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(self), 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)
}
}