'#selector' एक ऐसी विधि को संदर्भित करता है जो ऑब्जेक्टिव-सी के संपर्क में नहीं है


105

AddTarget के माध्यम से पैरामीटर को पारित करने वाला नया Xcode 7.3 आमतौर पर मेरे लिए काम करता है लेकिन इस मामले में यह शीर्षक में त्रुटि को फेंक रहा है। कोई विचार? यह एक और फेंकता है जब मैं इसे @objc में बदलने की कोशिश करता हूं

धन्यवाद!

cell.commentButton.addTarget(self, action: #selector(FeedViewController.didTapCommentButton(_:)), forControlEvents: UIControlEvents.TouchUpInside)

चयनकर्ता इसे बुला रहा है

func didTapCommentButton(post: Post) {
}

3
FeedViewController की वर्ग घोषणा रेखा क्या दिखती है? कैसे किया जाता है TTCommentButton? जब आप @objc जोड़ते हैं तो आपको क्या त्रुटि मिलती है?
टीकामा २४'१६

1
अपडेट, मैंने अपनी पोस्ट संपादित की। मैं अभी कंप्यूटर से दूर हूं, इसलिए मैं सटीक त्रुटि संदेश भूल गया हूं, लेकिन यह उन स्थितियों में से एक था जहां XCode मुझे इसे जोड़ने के लिए कहता है फिर अपने निर्णय पर एक त्रुटि फेंकता है।
इचज़ेल

2
क्या आपका वर्ग घोषित करता है @objc, या यह एक उपवर्ग है NSObject?
NRitH

2
क्या आप कोष्ठक हटाने की कोशिश कर सकते हैं? यह असामान्य है कि आप एक चयनकर्ता में एक फ़ंक्शन को कॉल न करें।
डैनियलड्रेसियन 3

इसने मेरी समस्या को एक दूसरे http://stackoverflow.com/a/36963058/1685165
Darko

जवाबों:


173

मेरे मामले में चयनकर्ता का कार्य था private। एक बार मैंने privateत्रुटि को हटा दिया था। उसी के लिए जाता है fileprivate

स्विफ्ट 4 में
आपको @objcफंक्शन डिक्लेरेशन में जोड़ना होगा । स्विफ्ट 4 तक यह अनुमान लगाया गया था।


2
के अतिरिक्त fileprivate
hstdt

जबरदस्त कैच @shaked
jbouaziz

@hstdt, इसलिए यदि आप सेट करते हैं, तो fileprivateक्या यह हल होगा?
हेमांग

2
@ हेमांग, नहीं, @hstdt का मतलब है कि न तो काम करेगा privateऔर न ही fileprivateकरेगा
Gobe

निजी / फ़ाइलपाइप को हटाने की तुलना में डायनेमिक के साथ फंक बनाना अधिक उपयुक्त है।
बून

57

इसके साथ उपयोग करने के लिए आपको @objcविशेषता का उपयोग करने की आवश्यकता है ।didTapCommentButton(_:)#selector

आप कहते हैं कि आपने ऐसा किया लेकिन आपको एक और त्रुटि मिली। मेरा अनुमान है कि नई त्रुटि यह है कि Postकोई ऐसा प्रकार नहीं है जो ऑब्जेक्टिव-सी के साथ संगत हो। आप केवल ऑब्जेक्टिव-सी के लिए एक विधि का खुलासा कर सकते हैं यदि इसके सभी प्रकार के तर्क, और इसके रिटर्न प्रकार, ऑब्जेक्टिव-सी के साथ संगत हैं।

आप उस का Postउपवर्ग बनाकर उसे ठीक कर सकते हैं NSObject, लेकिन इससे कोई फर्क नहीं पड़ता, क्योंकि तर्क तो वैसे भी didTapCommentButton(_:)नहीं होगा Post। एक्शन फंक्शन का तर्क एक्शन भेजने वाला है, और वह भेजने वाला होगा commentButton, जो कि संभवतः एक है UIButton। आपको didTapCommentButtonइस तरह की घोषणा करनी चाहिए :

@objc func didTapCommentButton(sender: UIButton) {
    // ...
}

फिर आपको Postटैप किए गए बटन के अनुरूप होने की समस्या का सामना करना पड़ेगा । इसे प्राप्त करने के कई तरीके हैं। यहां एक है।

मैं इकट्ठा करता हूं (जब से आपका कोड कहता है cell.commentButton) कि आप टेबल व्यू (या संग्रह दृश्य) सेट कर रहे हैं। और चूंकि आपके सेल में एक गैर-मानक संपत्ति है commentButton, जिसका नाम है , मुझे लगता है कि यह एक कस्टम UITableViewCellउपवर्ग है। तो चलिए मान लेते हैं कि आपका सेल PostCellइस तरह घोषित है:

class PostCell: UITableViewCell {
    @IBOutlet var commentButton: UIButton?
    var post: Post?

    // other stuff...
}

तब आप बटन को देखने के लिए पदानुक्रम को देख सकते हैं PostCell, और इससे पद प्राप्त कर सकते हैं:

@objc func didTapCommentButton(sender: UIButton) {
    var ancestor = sender.superview
    while ancestor != nil && !(ancestor! is PostCell) {
        ancestor = view.superview
    }
    guard let cell = ancestor as? PostCell,
        post = cell.post
        else { return }

    // Do something with post here
}

अगर मैं इसे वैश्विक समारोह के साथ उपयोग करना चाहता हूं? @objc can only be used with members of classes, @objc protocols, and concrete extensions of classes
टॉमसवीर

आप इसे वैश्विक फ़ंक्शन के साथ उपयोग नहीं कर सकते।
लूट मय

8

एक रैपर फ़ंक्शन के लिए चयनकर्ता बिंदु होने का प्रयास करें, जो बदले में आपके प्रतिनिधि फ़ंक्शन को कॉल करता है। मेरे लिए यही काम किया।

cell.commentButton.addTarget(self, action: #selector(wrapperForDidTapCommentButton(_:)), forControlEvents: UIControlEvents.TouchUpInside)

-

func wrapperForDidTapCommentButton(post: Post) {
     FeedViewController.didTapCommentButton(post)
}

1
मेरे लिए काम किया! अभी भी यकीन नहीं है कि यह क्यों आवश्यक है लेकिन मैं इसे ले जाऊंगा!
पॉल लेहंन

0

जैसा कि आप जानते हैं selector[के बारे में] कहते हैं कि Objective-Cरनटाइम का उपयोग किया जाना चाहिए। डिफ़ॉल्ट रूप से ऑब्जेक्टिव-सी रनटाइम के रूप में चिह्नित privateया घोषित नहीं किए गए घोषणाएं । यही कारण है कि आपके पास दो संस्करण हैं:fileprivate

  1. [के बारे में] द्वारा अपनी privateया fileprivateघोषणा को चिह्नित करें@objc
  2. का प्रयोग करें internal, public, openपहुँच संशोधक [बारे में]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.