मैं स्विफ्ट 4 में #selector () के साथ @objc इंट्रेंस डिप्रेशन से कैसे निपट सकता हूं?


131

मैं अपने प्रोजेक्ट के सोर्स कोड को स्विफ्ट 3 से स्विफ्ट 4 में बदलने की कोशिश कर रहा हूं। एक चेतावनी Xcode मुझे दे रहा है जो मेरे चयनकर्ताओं के बारे में है।

उदाहरण के लिए, मैं इस तरह एक नियमित चयनकर्ता का उपयोग करते हुए एक बटन के लिए एक लक्ष्य जोड़ता हूं:

button.addTarget(self, action: #selector(self.myAction), for: .touchUpInside)

यह चेतावनी से पता चलता है:

'#Selector' का तर्क 'ViewController' में इंस्टेंस विधि 'myAction ()' को संदर्भित करता है जो स्विफ्ट 4 में '@objc' विशेषता अनुमान पर निर्भर करता है।

इस उदाहरण विधि को ऑब्जेक्टिव-सी में उजागर करने के लिए '@objc' जोड़ें

अब, Fixत्रुटि संदेश पर मार मेरे कार्य के लिए है:

// before
func myAction() { /* ... */ }

// after
@objc func myAction() { /* ... */ }

मैं वास्तव में @objcचिह्न को शामिल करने के लिए अपने सभी कार्यों का नाम नहीं बदलना चाहता हूं और मैं मान रहा हूं कि यह आवश्यक नहीं है।

मैं चयनकर्ता को पुनर्वितरण से निपटने के लिए कैसे लिखूं?


संबंधित प्रश्न:


3
नहीं, उन्हें चिह्नित करने वाले के रूप में @objc है , ताकि उन्हें Obj सी को बेनकाब, और इसलिए चयनकर्ताओं के साथ उपयोग करने के लिए अब आवश्यक।
हमीश

3
तो पदावनत भाग सार्वजनिक-पहुंच कार्यों के रूप में है @objc? यह थोड़ा कष्टप्रद है, लेकिन मैं आम तौर पर इन कार्यों को निजी बनाता हूं, मुझे इसे @objcवैसे भी चिह्नित करने की आवश्यकता है ।
कॉनर

2
परिवर्तन के बारे में अधिक जानकारी के लिए SE-0160 देखें । एक अन्य विकल्प आपके दिए गए वर्ग को चिह्नित कर रहा @objcMembersहै ताकि ओबज-सी के सभी ओबज-सी संगत सदस्यों को बेनकाब किया जा सके, लेकिन मैं यह सलाह नहीं दूंगा कि जब तक आपको वास्तव में आपके पूरे वर्ग को उजागर करने की आवश्यकता नहीं है।
हमीश

3
@LinusGeffarth जैसा कि प्रस्ताव में कहा गया है, यह संभवतः आपके बाइनरी के आकार में अनावश्यक वृद्धि करेगा और गतिशील लिंकिंग में अधिक समय लगेगा। मुझे नहीं लगता है कि यह स्पष्टता के लिए बहुत अधिक परेशानी है कि आप विशेष रूप से ओब्ज-सी से इस्तेमाल होने वाली किसी विशेष चीज के लिए हैं।
हमीश

1
कोशिश की, काम नहीं किया।
लाइनुसेफर्थ

जवाबों:


156

फिक्स-यह सही है - ऑब्जेक्टिव-सी के संपर्क में आने वाली विधि को बनाने के लिए आप चयनकर्ता के बारे में कुछ भी नहीं बदल सकते हैं।

पहली बार में इस चेतावनी का पूरा कारण SE-0160 का परिणाम है । स्विफ्ट 4 से पहले, internalया NSObjectविरासत वाले वर्गों के उच्च उद्देश्य-सी संगत सदस्य होने का अनुमान लगा रहे थे @objcऔर इसलिए ऑब्जेक्टिव-सी के संपर्क में थे, इसलिए उन्हें चयनकर्ताओं का उपयोग करने के लिए बुलाया जा सकता था (विधि के रूप में देखने के लिए ओब्ज-सी रनटाइम आवश्यक है। किसी दिए गए चयनकर्ता के लिए कार्यान्वयन)।

हालाँकि स्विफ्ट 4 में, अब ऐसा नहीं है। केवल बहुत विशिष्ट घोषणाओं का अनुमान लगाया जा सकता है @objc, उदाहरण के लिए, @objcतरीकों की ओवरराइड , @objcप्रोटोकॉल आवश्यकताओं के कार्यान्वयन और उन विशेषताओं के साथ घोषणाएं जो @objcइस तरह की हैं @IBOutlet

इसके पीछे की प्रेरणा, जैसा कि ऊपर दिए गए प्रस्ताव में बताया गया है , सबसे पहले NSObjectसमान चयनकर्ताओं के कारण विरासत की कक्षाओं को एक-दूसरे से टकराने से रोकने में विधि अधिभार को रोकने के लिए है। दूसरे, यह द्विआधारी आकार को कम करने में मदद करता है ताकि सदस्यों के लिए थ्रॉक्स उत्पन्न न हो जो ओब्ज-सी के संपर्क में न हो, और तीसरा गतिशील लिंकिंग की गति में सुधार करता है।

यदि आप ओब्ज-सी के लिए एक सदस्य को उजागर करना चाहते हैं, तो आपको इसे @objcउदाहरण के लिए चिह्नित करना होगा :

class ViewController: UIViewController {

    @IBOutlet weak var button: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        button.addTarget(self, action: #selector(foo), for: .touchUpInside)
    }

    @objc func foo() {
       // ... 
    }
}

(माइग्रेटर को आपके लिए चयनित चयनकर्ताओं के साथ स्वचालित रूप से ऐसा करना चाहिए जब "चयनित अनुमान" विकल्प के साथ चल रहा हो)

ओबज-सी के सदस्यों के एक समूह को बेनकाब करने के लिए, आप एक का उपयोग कर सकते हैं @objc extension:

@objc extension ViewController {

    // both exposed to Obj-C
    func foo() {}
    func bar() {}
}

यह ओबज-सी में परिभाषित किए गए सभी सदस्यों को उजागर करेगा, और ओब्ज-सी (जब तक स्पष्ट रूप से चिह्नित नहीं किया जाएगा) को उजागर नहीं किया जा सकता है @nonobjc

यदि आपके पास एक वर्ग है जहाँ आपको ओब्ज-सी के लिए सभी ओब्ज-सी संगत सदस्यों की आवश्यकता है, तो आप क्लास को इस प्रकार चिन्हित कर सकते हैं @objcMembers:

@objcMembers
class ViewController: UIViewController {
   // ...
}

अब, सभी सदस्य होने का अनुमान लगाया जा @objcसकता है। हालाँकि, मैं ऐसा करने की सलाह नहीं दूंगा जब तक कि आपको वास्तव में ओबज-सी के संपर्क में आने वाले सभी सदस्यों की आवश्यकता न हो , उपरोक्त सदस्यों द्वारा अनावश्यक रूप से उजागर किए गए उल्लिखित को देखते हुए।


2
कोड को नवीनतम सिंटैक्स में परिवर्तित करते समय Xcode स्वचालित रूप से ऐसा क्यों नहीं करता है?
लिनसग्राफर्थ

1
मुझे आश्चर्य है, @IBActionस्वचालित रूप से भी हैं @objc? अब तक ऐसा नहीं था लेकिन यह तर्कसंगत होगा। EDIT: nvm, प्रस्ताव स्पष्ट रूप से बताता है कि @IBActionएक विधि के लिए पर्याप्त है @objc
सुल्तान

8
मुझे इसका कोई मतलब समझ में नहीं आ रहा है। मेरा कोई उद्देश्य-सी-कोड नहीं है तो क्या हुआ। क्या किसी बटन पर लक्ष्य जोड़ने का कोई शुद्ध स्विफ्ट-तरीका नहीं है? या चयनकर्ताओं का उपयोग करें? मैं नहीं चाहता कि मेरे कोड को इस विशेषता के साथ जोड़ा जाए। क्या ऐसा इसलिए है क्योंकि एक UIButton कुछ NSObject / Obj-c-thing से लिया गया है?
Sti

11
@Sti तो सीधे जवाब देने के लिए " क्या बटन में लक्ष्य जोड़ने का कोई शुद्ध स्विफ्ट-तरीका नहीं है? या चयनकर्ताओं का उपयोग करें? " - नहीं, चयनकर्ताओं को विधियों को भेजने के लिए उपयोग करने का कोई "शुद्ध स्विफ्ट" तरीका नहीं है। वे ओब्ज-सी रनटाइम पर भरोसा करते हैं ताकि किसी विशेष चयनकर्ता को कॉल करने के लिए विधि कार्यान्वयन को देखने के लिए - स्विफ्ट रनटाइम में वह क्षमता न हो।
हमीश

12
मैन सिलेक्टर्स एक गड़बड़ हैं। ऐसा लगता है कि हर दूसरे स्विफ्ट अपडेट में वे इसके साथ खिलवाड़ कर रहे हैं। हम सिर्फ तरीकों के लिए एक शुद्ध स्विफ्ट स्वत: पूर्ण चयनकर्ता क्यों नहीं कर सकते। कोड बदसूरत लग रहा है।
जॉन रिसेल्वाटो

16

के रूप में एप्पल आधिकारिक प्रलेखन । आपको अपने चयनकर्ता विधि को कॉल करने के लिए @objc का उपयोग करने की आवश्यकता है।

ऑब्जेक्टिव-सी में, एक चयनकर्ता एक प्रकार है जो ऑब्जेक्ट-सी पद्धति के नाम को संदर्भित करता है। स्विफ्ट में, उद्देश्य-सी चयनकर्ताओं को Selectorसंरचना द्वारा दर्शाया जाता है , और #selector अभिव्यक्ति का उपयोग करके इसका निर्माण किया जा सकता है । एक विधि के लिए चयनकर्ता बनाने के लिए जिसे ऑब्जेक्टिव-सी से बुलाया जा सकता है, विधि का नाम, जैसे कि पास करें #selector(MyViewController.tappedButton(sender:))। किसी प्रॉपर्टी के ऑब्जेक्टिव-सी गेट्टर या सेटर मेथड के लिए चयनकर्ता का निर्माण करने के लिए, प्रॉपर्टी के नाम को उपसर्ग getter:या setter:लेबल से पास करें, जैसे #selector(getter: MyViewController.myButton)


मुझे यह सब समझ में आता है कि कुछ मामलों में मुझे @objc को एक फंक की शुरुआत में जोड़ने की आवश्यकता है, चाहे मैं इसे ऑब्जेक्टिव-सी से कॉल करने जा रहा हूं या नहीं। मैं बस सीख रहा हूँ स्विफ्ट ने सालों से
ओबज

10

जैसा कि, मुझे लगता है कि Swift 4.2, आपको बस इतना करना है कि @IBAction को अपने तरीके से असाइन करें और आप इस मूर्खतापूर्ण @objc एनोटेशन से बच सकते हैं

`` `

let tap  =  UITapGestureRecognizer(target: self, action: #selector(self.cancel))


@IBAction func cancel()
{
    self.dismiss(animated: true, completion: nil)
}

1
यह इंटरफ़ेस बिल्डर को यह भी बताएगा कि यह फ़ंक्शन कनेक्ट किया जा सकता है, जो कि आप जो चाहते हैं वह नहीं हो सकता है। यह @objc जैसी ही बात भी कर रहा है।
जोश पैराडायराइड

2

जैसा कि पहले से ही अन्य उत्तरों में बताया गया है, इससे बचने का कोई उपाय नहीं है @objc चयनकर्ताओं के लिए एनोटेशन ।

लेकिन ओपी में उल्लिखित चेतावनी को निम्नलिखित कदम उठाकर चुप कराया जा सकता है:

  1. बिल्ड सेटिंग्स पर जाएं
  2. कीवर्ड के लिए खोज करें @objc
  3. का मूल्य निर्धारित करें स्विफ्ट 3 @objc इंटरफ़ेस करने के लिएOff

नीचे स्क्रीनशॉट है जो उपर्युक्त चरणों को दिखाता है:

चेतावनी "स्विफ्ट 3 @objc इंटरफ़ेस"

उम्मीद है की यह मदद करेगा


यह आपके प्रोजेक्ट को बड़ी तस्वीर में कैसे प्रभावित करता है?
जोनली जेम

1
कैसे के बारे में * .ipa या *। मूल आकार, और समय का निर्माण?
ज़ोनली जैम

@ZonilyJame मैंने निर्माण समय पर ध्यान नहीं दिया, लेकिन आईपीए के आकार पर कोई प्रभाव नहीं पड़ा
S1LENT WARRIOR

यदि आप Apple दिशानिर्देशों के अनुसार स्विफ्ट 4.0+ संस्करण का उपयोग करते हैं तो यह अनुशंसित मूल्य नहीं है। इस मदद की
।apple.com

1
आप मान को Xcode 11 में डिफ़ॉल्ट पर सेट करके इस उत्तर को अपडेट कर सकते हैं। यह पूरी तरह से चेतावनी को हटाने के लिए परियोजना और आपके लक्ष्य दोनों पर मूल्य निर्धारित करने के लिए महत्वपूर्ण है।
टॉमी सी।

2

यदि आपको अपने व्यू कंट्रोलर में ऑब्जेक्टिव c मेंबर्स की जरूरत है तो व्यू कंट्रोलर के सबसे ऊपर @objcMembers जोड़ें । और आप अपने कोड में IBAction जोड़कर इससे बच सकते हैं।

@IBAction func buttonAction() {

}

इस आउटलेट को स्टोरीबोर्ड में कनेक्ट करना सुनिश्चित करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.