iOS 13.0 및 이전 버전에서 CNContactViewController에 연락처를 추가하기 위해 예상대로 작동하므로 iOS 13.1에만 해당되는 것으로 보입니다. 수행중인 작업이없고 키보드가 닫히지 않습니다.
답변
위대한 해결 방법을 위해 @GxocT에 대한 찬사! 내 사용자들을 엄청나게 도와주었습니다.
그러나 @GxocT 솔루션을 기반으로 코드를 공유하고 싶었습니다.이 시나리오에서 다른 사람들에게 도움이되기를 바랍니다.
나는 CNContactViewControllerDelegate
contactViewController(_:didCompleteWith:)
취소 할 때뿐만 아니라 전화해야했습니다.
또한 내 코드가 아니 었 UIViewController
으므로self.navigationController
나는 또한 그것을 도울 수있을 때 강제로 풀기를 사용하는 것을 좋아하지 않습니다. 나는 과거에 물렸으므로 if let
셋업에서 체인을 연결 했습니다.
내가 한 일은 다음과 같습니다.
-
CNContactViewController
swizzle 기능을 확장 하고 배치하십시오
. -
내 경우에는 swizzle 함수 에서 연락처 컨트롤러 와 함께
CNContactViewControllerDelegate
대리자
contactViewController(_:didCompleteWith:)
를 호출self
하고
self.contact
객체를 객체에서 -
설정 코드에서 swizzleMethod 호출이
대신 클래스 를class_getInstanceMethod
지정 하는지 확인하십시오.
CNContactViewController
self
그리고 스위프트 코드 :
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)
}
}
키보드는 여전히 잠깐 동안 표시되지만 연락처 컨트롤러가 해제 된 직후에 삭제됩니다.
사과가 이것을 고치기를 바랍니다.
답변
키보드를 해제하는 방법을 찾을 수 없습니다. 그러나 적어도 내 방법을 사용하여 ViewController를 팝업 할 수 있습니다.
- 이유를 모르지만 CNContactViewController에서 키보드를 해제하는 것은 불가능합니다. endEditing :을 시도하고 새로운 UITextField firstResponder 등을 만듭니다. 아무것도 효과가 없었습니다.
- “취소”버튼의 동작을 변경하려고했습니다. NavigationController 스택에서이 버튼을 찾을 수 있지만 무언가를 입력 할 때마다 동작이 변경됩니다.
- 마지막으로 메소드 스위 즐링을 사용했습니다. 앞에서 언급 한대로 키보드를 해제하는 방법을 찾을 수 없었지만 “취소”버튼을 누르면 적어도 CNContactViewController를 해제 할 수 있습니다.
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)
}
}
}
추신 : reddit 주제에 대한 추가 정보를 찾을 수 있습니다 : https://www.reddit.com/r/swift/comments/dc9n3a/bug_with_cnviewcontroller_ios_131/
답변
사용자는 실제로 아래로 스 와이프하여 키보드를 닫은 다음 취소를 탭하고 작업 시트를 볼 수 있습니다. 따라서이 문제는 유감스럽고 분명히 버그 (및 버그 보고서를 제출했지만) 치명적이지는 않습니다 (확실히 말하면 해결 방법은 사용자가 쉽게 알 수 없습니다).
답변
Xcode Simulator에서 테스트 한 iOS 13.4에서 수정되었습니다.
답변
그의 훌륭한 작업에 대해 @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)
}
}