Bàn phím chồng lên bảng hành động trong iOS 13.1 trên CNContactViewCont kiểm


12

Điều này dường như dành riêng cho iOS 13.1, vì nó hoạt động như mong đợi trên iOS 13.0 và các phiên bản trước đó để thêm một liên hệ trong CNContactViewCont kiểm soát, nếu tôi 'Hủy', bảng hành động bị chồng chéo bởi bàn phím. Không có hành động nào được thực hiện và bàn phím không bị loại bỏ.

Câu trả lời:


5

Kudos gửi @GxocT cho cách giải quyết tuyệt vời! Đã giúp người dùng của tôi rất nhiều.
Nhưng tôi muốn chia sẻ mã của mình dựa trên giải pháp @GxocT với hy vọng nó sẽ giúp những người khác trong kịch bản này.

Tôi cần CNContactViewControllerDelegate contactViewController(_:didCompleteWith:)được gọi để hủy bỏ (cũng như được thực hiện).

Ngoài ra mã của tôi không ở trong UIViewControllernên không cóself.navigationController

Tôi cũng không thích sử dụng vũ lực khi tôi có thể giúp nó. Tôi đã bị cắn trong quá khứ vì vậy tôi đã xiềng xích if lettrong thiết lập

Đây là những gì tôi đã làm:

  1. Mở rộng CNContactViewControllervà đặt chức năng swizzle trong
    đó.

  2. Trong trường hợp của tôi trong hàm sự gian lận chỉ cần gọi các
    CNContactViewControllerDelegateđại biểu
    contactViewController(_:didCompleteWith:)với self
    self.contactđối tượng từ bộ điều khiển liên lạc

  3. Trong mã thiết lập, đảm bảo lệnh gọi swizzleMethod để class_getInstanceMethodchỉ định CNContactViewController lớp thay vìself

Và mã 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)
    }
}

Bàn phím vẫn hiển thị trong giây lát nhưng giảm xuống ngay sau khi bộ điều khiển Danh bạ tắt.
Hãy hy vọng táo sửa lỗi này


buộc unraps được sử dụng để làm cho mã nhỏ gọn tất nhiên bạn nên tránh chúng nếu có thể và nếu nó có thể dẫn đến sự cố. btw tôi không chắc liệu có đúng không khi tự mình giao phó, vì có thể nó không được tạo nếu bạn hủy luồng ps: đã thay đổi cách triển khai của tôi để tránh bị hủy bỏ: D
GxocT

@GxocT - đồng ý về lực lượng urwraps. Và chúng không phải lúc nào cũng khủng khiếp nhưng những người khác không thích bạn và có thể luôn sử dụng chúng mà không nhận ra rủi ro;). Tôi thích nếu để thay vì! khi tôi không chắc chắn 100% thì nó sẽ không còn nữa. Về self.contact - đúng là tôi không biết mã lib của Apple thường truyền cho đại biểu nội bộ nhưng self.contact có dữ liệu liên hệ và tài liệu CNContactViewControll nói rằng đó là "liên hệ được hiển thị" nên có vẻ như sử dụng được. Mã của tôi không thực sự sử dụng liên hệ được truyền trong đại biểu hoàn thành để tôi chỉ có thể chuyển số không trong phần mở rộng.
Barrett

Các nội dung (bao gồm các chế độ xem văn bản và bàn phím) trong CNContactViewControll phải ở trong một quy trình riêng. Nếu bạn có thể sử dụng 'Xem phân cấp' trong Xcode cho trình điều khiển chế độ xem này, bạn có thể thấy nội dung không thể nhìn thấy. Do đó, chúng tôi không thể điều khiển bàn phím cũng như chế độ xem văn bản.
WildCat

5

Tôi không thể tìm cách loại bỏ bàn phím. Nhưng ít nhất bạn có thể bật ViewContoder bằng phương pháp của tôi.

  1. Không biết tại sao nhưng không thể loại bỏ bàn phím trong CNContactViewCont kiểm. Tôi đã thử endEditing:, tạo UITextField mới đầu tiênResponder, v.v. Không có gì làm việc.
  2. Tôi đã cố gắng thay đổi hành động cho nút "Hủy". Bạn có thể tìm thấy nút này trong ngăn xếp NavigationContoder, nhưng hành động của nó được thay đổi mỗi khi bạn gõ một cái gì đó.
  3. Cuối cùng tôi đã sử dụng phương pháp swizzling. Tôi không thể tìm cách loại bỏ bàn phím như tôi đã đề cập trước đó, nhưng ít nhất bạn có thể loại bỏ CNContactViewCont kiểm soát khi nhấn nút "Hủy".
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: Bạn có thể tìm thấy thông tin bổ sung về chủ đề reddit: https://www.reddit.com/r/swift/comments/dc9n3a/orms_with_cnviewcontroll_ios_131/


2

Trên thực tế, người dùng có thể vuốt xuống để tắt bàn phím và sau đó nhấn Hủy và xem bảng hành động. Vì vậy, vấn đề này là đáng tiếc và chắc chắn là một lỗi (và tôi đã nộp báo cáo lỗi) nhưng không gây tử vong (mặc dù, để chắc chắn, cách giải quyết không phải là nhỏ đối với người dùng khám phá).

nhập mô tả hình ảnh ở đây


Bạn có thể liên kết đến báo cáo lỗi bạn đã nộp?
Paaske

1

Đã sửa lỗi trong iOS 13.4 Đã thử nghiệm trong Xcode Simulator


1

Cảm ơn @Gxoct cho công việc tuyệt vời của mình xung quanh. Tôi nghĩ rằng đây là câu hỏi và bài viết rất hữu ích cho những người đang làm việc với CNContactViewController. Tôi cũng có vấn đề này (cho đến bây giờ) nhưng trong mục tiêu c. Tôi diễn giải mã Swift ở trên thành mục tiêu 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);
    }
}

Tạo một CNContactViewControllerthể loại để truy cập sa thải;

@implementation CNContactViewController (Test)

- (void) dismiss{
    [self.delegate contactViewController:self didCompleteWithContact:self.contact];
}

@end

Những anh chàng không quá quen thuộc với Swizzling bạn có thể thử bài này của matt


0

Cảm ơn, @GxocT vì cách giải quyết của bạn, tuy nhiên, giải pháp được đăng ở đây khác với giải pháp bạn đã đăng trên Reddit.

Cái trên Reddit hoạt động với tôi, cái này không có nên tôi muốn đăng lại ở đây. Sự khác biệt là trên dòng với swizzledMethod nên:

   let swizzledMethod = class_getInstanceMethod(object_getClass(self), swizzledSelector) {

Toàn bộ mã được cập nhật là:

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)
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.