सीएनसी कांटेक्ट व्यूक्रांटर पर iOS 13.1 में कीबोर्ड ओवरलेइंग एक्शन शीट


12

यह iOS 13.1 के लिए विशिष्ट प्रतीत होता है, क्योंकि यह iOS 13.0 और पुराने संस्करणों पर अपेक्षित रूप से कार्य करता है, क्योंकि यह 'कैंसल' करता है, कीबोर्ड द्वारा ओवरलैप करने पर सीएनसीॉन्टैक्टव्यूकंट्रोलर में संपर्क जोड़ने के लिए। कोई कार्रवाई नहीं हो रही है और कीबोर्ड खारिज नहीं कर रहा है।

जवाबों:


5

महान वर्कअराउंड के लिए @GxocT के लिए यश! मेरे उपयोगकर्ताओं की बहुत मदद की।
लेकिन मैं @GxocT समाधान के आधार पर अपने कोड को साझा करना चाहता था उम्मीद है कि यह इस परिदृश्य में दूसरों की मदद करेगा।

मुझे जरूरत थी कि मुझे CNContactViewControllerDelegate contactViewController(_:didCompleteWith:)रद्द (साथ ही साथ) रद्द कर दिया जाए।

इसके अलावा मेरा कोड नहीं था UIViewControllerइसलिए वहाँ कोई नहीं हैself.navigationController

मैं भी जब मैं इसे मदद कर सकते हैं बल प्रयोग नहीं पसंद है। मुझे अतीत में काट दिया गया है इसलिए मैंने if letसेटअप में एस को जंजीर किया

यहाँ मैंने क्या किया है:

  1. विस्तृत करें CNContactViewControllerऔर
    वहां स्विज़ल फ़ंक्शन रखें ।

  2. स्विज़ल फ़ंक्शन में मेरे मामले में बस संपर्क नियंत्रक से
    CNContactViewControllerDelegateप्रतिनिधि और ऑब्जेक्ट के
    contactViewController(_:didCompleteWith:)साथ कॉल करेंself
    self.contact

  3. सेटअप कोड में, सुनिश्चित करें कि 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)
    }
}

कीबोर्ड अभी भी पल-पल दिखाता है लेकिन संपर्क नियंत्रक के खारिज होने के बाद ही गिरता है।
आशा है कि सेब इसे ठीक करता है


फोर्स अल्ट्राप्स का उपयोग कोड कॉम्पैक्ट बनाने के लिए किया जाता है बेशक आपको उनसे बचना चाहिए और यदि संभव हो तो दुर्घटना हो सकती है। btw मुझे यकीन नहीं है कि अगर यह स्वयं को पास करने के लिए सही है। प्रतिनिधि को सौंपने का कारण है, तो इसका कारण यह नहीं है कि यदि आप प्रवाह पीएस को रद्द करते हैं: बल के
जाल

@GxocT - बल urwraps पर सहमत हुए। और वे हमेशा भयानक नहीं होते हैं, लेकिन अन्य आपके जैसे नहीं होते हैं और जोखिम का एहसास किए बिना हमेशा उनका उपयोग कर सकते हैं;)। मुझे पसंद है अगर इसके बजाय चलो! जब मैं 100% यकीन नहीं है कि यह शून्य होगा। Self.contact के बारे में - यह सच है कि मुझे पता नहीं है कि Apple का lib कोड आम तौर पर प्रतिनिधि के पास आंतरिक रूप से जाता है, लेकिन self.contact के पास संपर्क डेटा था और CNContactViewController डॉक्टर का कहना है कि यह "संपर्क प्रदर्शित किया जा रहा है" इसलिए इसका उपयोग करना ठीक लग रहा था। मेरा कोड वास्तव में पूरा होने वाले प्रतिनिधि में पास किए गए संपर्क का उपयोग नहीं करता है, इसलिए मैं विस्तार में शून्य पास कर सकता हूं।
बैरेट

सीएनसीॉन्टैक्टव्यूकंट्रोलर में सामग्री (incl। टेक्स्ट व्यू और कीबोर्ड) एक अलग प्रक्रिया में होनी चाहिए। यदि आप इस दृश्य नियंत्रक के लिए Xcode में 'व्यू पदानुक्रम' का उपयोग कर सकते हैं, तो आप पा सकते हैं कि सामग्री देखी नहीं जा सकती। परिणामस्वरूप, हम कीबोर्ड और न ही टेक्स्ट दृश्य को नियंत्रित नहीं कर सकते।
वाइल्डकैट

5

मुझे कीबोर्ड को खारिज करने का कोई तरीका नहीं मिला। लेकिन कम से कम आप मेरी विधि का उपयोग करके ViewController पॉप कर सकते हैं।

  1. पता नहीं क्यों, लेकिन सीएनसीटैक्टव्यूकॉन्ट्रोलर में कीबोर्ड को खारिज करना असंभव है। मैंने अंतिम प्रयास किया: नया UITextField फर्स्टResponder इत्यादि बनायें। कुछ भी काम नहीं किया।
  2. मैंने "रद्द करें" बटन के लिए कार्रवाई को बदलने की कोशिश की। इस बटन को आप नेवीगेशनकंट्रोलर स्टैक में पा सकते हैं, लेकिन हर बार जब आप कुछ टाइप करते हैं तो यह क्रिया बदल जाती है।
  3. अंत में मैंने मेथड स्विज़लिंग का इस्तेमाल किया। जैसा कि मैंने पहले उल्लेख किया था, मुझे कीबोर्ड को खारिज करने का कोई तरीका नहीं मिला, लेकिन जब "रद्द करें" बटन दबाया जाता है, तो कम से कम आप सीएनसी कांटैक्ट व्यू कॉन्ट्रोलर को खारिज कर सकते हैं।
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/


2

उपयोगकर्ता वास्तव में कीबोर्ड को खारिज करने के लिए नीचे स्वाइप कर सकता है और फिर रद्द करें पर टैप करके एक्शन शीट देख सकता है। तो यह मुद्दा खेदजनक है और निश्चित रूप से एक बग (और मैंने एक बग रिपोर्ट दर्ज की है) लेकिन घातक नहीं है (हालांकि, यह सुनिश्चित करने के लिए कि उपयोगकर्ता को खोजने के लिए वैकल्पिक हल नहीं है)।

यहां छवि विवरण दर्ज करें


क्या आप अपने द्वारा दर्ज की गई बग रिपोर्ट से लिंक कर सकते हैं?
पास्का

1

IOS 13.4 में तय Xcode सिम्युलेटर में परीक्षण किया गया


1

धन्यवाद @Gxoct अपने उत्कृष्ट काम के लिए चारों ओर। मुझे लगता है कि यह उन लोगों के लिए बहुत उपयोगी प्रश्न है, जिनके साथ काम कर रहे हैं CNContactViewController। मुझे भी यह समस्या थी (अब तक) लेकिन उद्देश्य सी में। मैं उपरोक्त स्विफ्ट कोड को उद्देश्य 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 से इतने परिचित नहीं हैं आप इस पोस्ट को मैट द्वारा आज़मा सकते हैं


0

धन्यवाद, @GxocT आपके वर्कअराउंड के लिए, हालाँकि, यहां पर पोस्ट किया गया समाधान आपके द्वारा 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)
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.