मैं 'शुद्ध' स्विफ्ट (@objc के बिना) में एक कमजोर प्रोटोकॉल संदर्भ कैसे बना सकता हूं


561

weakसंदर्भ स्विफ्ट में तब तक काम नहीं करते हैं जब तक कि एक के protocolरूप में घोषित नहीं किया जाता है @objc, जो मैं एक शुद्ध स्विफ्ट ऐप में नहीं चाहता हूं।

यह कोड एक संकलित त्रुटि देता है ( weakगैर-श्रेणी प्रकार पर लागू नहीं किया जा सकता MyClassDelegate):

class MyClass {
  weak var delegate: MyClassDelegate?
}

protocol MyClassDelegate {
}

मुझे प्रोटोकॉल के साथ उपसर्ग करने की आवश्यकता है @objc, फिर यह काम करता है।

प्रश्न: एक पूरा करने के लिए 'शुद्ध' स्विफ्ट तरीका क्या है weak delegate?


ध्यान दें ... stackoverflow.com/a/60837041/294884
फेटी

जवाबों:


1038

आपको प्रोटोकॉल के प्रकार को घोषित करने की आवश्यकता है AnyObject

protocol ProtocolNameDelegate: AnyObject {
    // Protocol stuff goes here
}

class SomeClass {
    weak var delegate: ProtocolNameDelegate?
}

AnyObjectआप का उपयोग करते हुए कहते हैं कि केवल कक्षाएं इस प्रोटोकॉल के अनुरूप हो सकती हैं, जबकि संरचना या एनम नहीं कर सकते।


25
इस समाधान के साथ मेरी समस्या यह है कि प्रतिनिधि को बुलाने से दुर्घटना हो जाती है - EXC_BAD_ACCESS (जैसा कि अन्य लोगों द्वारा उल्लेख किया गया है)। यह बग लगता है। एकमात्र समाधान जो मैंने पाया है वह @objc का उपयोग करना और प्रोटोकॉल से सभी स्विफ्ट डेटा प्रकारों को समाप्त करना है।
जिम टी।

12
स्विफ्ट में अब कमजोर प्रतिनिधियों को करने का सही तरीका क्या है? Apple प्रलेखन अपने उदाहरण कोड में प्रतिनिधि को कमजोर नहीं दिखा रहा है या घोषित नहीं कर रहा है: developer.apple.com/library/ios/documentation/swift/conceptual/…
C0D3

2
यह हमेशा सुरक्षित नहीं होता है - याद रखें कि आपको केवल प्रतिनिधि को कमजोर बनाने की आवश्यकता है यदि यह प्रतिनिधि को भी संदर्भित करता है और आपको उस मजबूत संदर्भ चक्र को तोड़ने की आवश्यकता है। यदि प्रतिनिधि प्रतिनिधि के लिए कोई संदर्भ नहीं रखता है, तो प्रतिनिधि गुंजाइश से बाहर जा सकता है (क्योंकि यह कमजोर है) और आपके पास क्रैश और अन्य समस्याएं होंगी: / कुछ को ध्यान में रखना होगा।
ट्रेव 14

5
BTW: मुझे लगता है कि "नई शैली" (स्विफ्ट 5) करना है protocol ProtocolNameDelegate: AnyObject, लेकिन कोई फर्क नहीं पड़ता।
होह

1
यह तब होना चाहिए AnyObjectजब classकिसी बिंदु पर पदावनत किया जाएगा।
जोस

283

अनुपूरक उत्तर

मैं हमेशा इस बात को लेकर उलझन में था कि प्रतिनिधि कमजोर हों या नहीं। हाल ही में मैंने प्रतिनिधियों के बारे में अधिक सीखा है और जब कमजोर संदर्भों का उपयोग करना है, तो मुझे भविष्य के दर्शकों के लिए यहां कुछ पूरक बिंदुओं को जोड़ना चाहिए।

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

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

  • weakसंदर्भ हमेशा वैकल्पिक होते हैं (अन्यथा आप उपयोग किए जाते हैं unowned) और हमेशा उपयोग करते हैं var(नहीं let) ताकि वैकल्पिक को nilतब तक सेट किया जा सके जब उसे निपटाया जाए।

  • एक मूल वर्ग को स्वाभाविक रूप से अपने बच्चे की कक्षाओं के लिए एक मजबूत संदर्भ होना चाहिए और इस तरह से weakकीवर्ड का उपयोग नहीं करना चाहिए । जब कोई बच्चा अपने माता-पिता के लिए एक संदर्भ चाहता है, हालांकि, उसे weakकीवर्ड का उपयोग करके इसे एक कमजोर संदर्भ बनाना चाहिए ।

  • weakजब आप एक ऐसे वर्ग का संदर्भ चाहते हैं जिसका उपयोग आप स्वयं नहीं करते हैं, न कि केवल अपने माता-पिता को संदर्भित करने वाले बच्चे के लिए। जब दो गैर-पदानुक्रमित वर्गों को एक-दूसरे का संदर्भ देने की आवश्यकता होती है, तो कमजोर होने के लिए एक को चुनें। आप जो चुनते हैं वह स्थिति पर निर्भर करता है। इस प्रश्न के उत्तर इस पर और देखें ।

  • एक सामान्य नियम के रूप में, प्रतिनिधियों को चिह्नित किया जाना चाहिएweak क्योंकि अधिकांश प्रतिनिधि कक्षाओं का संदर्भ दे रहे हैं जो उनके पास नहीं है। यह निश्चित रूप से सच है जब एक बच्चा एक प्रतिनिधि के साथ एक माता-पिता के साथ संवाद करने के लिए उपयोग कर रहा है। प्रतिनिधि के लिए एक कमजोर संदर्भ का उपयोग करना दस्तावेज़ीकरण की सिफारिश करता है। (लेकिन यह भी देखें ।)

  • प्रोटोकॉल का उपयोग संदर्भ प्रकार (कक्षाएं) और मूल्य प्रकार (संरचना, एनम) दोनों के लिए किया जा सकता है । तो इस मामले में कि आपको एक प्रतिनिधि को कमजोर बनाने की आवश्यकता है, आपको इसे केवल एक ऑब्जेक्ट-प्रोटोकॉल बनाना होगा। ऐसा करने का तरीका AnyObjectप्रोटोकॉल की वंशानुक्रम सूची में जोड़ना है। (अतीत में आपने classकीवर्ड का उपयोग करके ऐसा किया था , लेकिन AnyObjectअब इसे पसंद किया जाता है ।)

    protocol MyClassDelegate: AnyObject {
        // ...
    }
    
    class SomeClass {
        weak var delegate: MyClassDelegate?
    }

आगे के अध्ययन

निम्नलिखित लेखों को पढ़ने से मुझे इतना बेहतर समझने में मदद मिली। वे unownedकीवर्ड से संबंधित मुद्दों और मजबूत संदर्भ चक्रों पर भी चर्चा करते हैं जो क्लोजर के साथ होते हैं।

सम्बंधित


5
यह सब अच्छा और दिलचस्प है, लेकिन वास्तव में मेरे मूल प्रश्न से संबंधित नहीं है - जो न तो कमजोर / एआरसी के बारे में है और न ही इस बारे में कि प्रतिनिधि आमतौर पर कमजोर क्यों हैं। हम पहले से ही उस सब के बारे में जानते हैं और आश्चर्यचकित हैं कि आप एक कमजोर प्रोटोकॉल संदर्भ (@flainez द्वारा पूरी तरह से अच्छी तरह से उत्तर) की घोषणा कैसे कर सकते हैं।
होन

30
आप सही हे। मेरे पास वास्तव में आपके जैसा ही प्रश्न था, लेकिन मुझे इस पृष्ठभूमि की बहुत सारी जानकारी याद आ रही थी। मैंने उपरोक्त रीडिंग की और अपने प्रश्न से संबंधित सभी मुद्दों को समझने में मदद करने के लिए पूरक नोट्स बनाए। अब मुझे लगता है कि मैं आपके स्वीकृत उत्तर को लागू कर सकता हूं और जान सकता हूं कि मैं ऐसा क्यों कर रहा हूं। मुझे उम्मीद है कि शायद यह भविष्य के दर्शकों को भी मदद करेगा।
सुरगाच

5
लेकिन क्या मेरे पास एक कमजोर प्रोटोकॉल है जो कि प्रकार पर निर्भर नहीं करता है? अपने आप से एक प्रोटोकॉल परवाह नहीं करता है कि कौन सी वस्तु स्वयं के अनुरूप है। तो एक वर्ग, या एक संरचना दोनों इसके अनुरूप हो सकते हैं। क्या अभी भी संभव है कि दोनों को इसके अनुरूप लाभ मिल सके, लेकिन केवल उसी प्रकार के वर्ग हैं जो अनुरूप हैं?
फ्लोयू। SimpleUITesting.com

> क्योंकि अधिकांश प्रतिनिधि वर्गों को संदर्भित कर रहे हैं कि उनके पास ऐसा नहीं है कि मैं इसे फिर से लिखूंगा: अधिकांश प्रतिनिधि। अन्यथा गैर-स्वामित्व वाली वस्तु मालिक बन जाती है
विक्टर जलकेन

36

AnyObject स्विफ्ट में कमजोर संदर्भ का उपयोग करने का आधिकारिक तरीका है।

class MyClass {
    weak var delegate: MyClassDelegate?
}

protocol MyClassDelegate: AnyObject {
}

Apple से:

मजबूत संदर्भ चक्र को रोकने के लिए, प्रतिनिधियों को कमजोर संदर्भ के रूप में घोषित किया जाना चाहिए। कमजोर संदर्भों के बारे में अधिक जानकारी के लिए, कक्षा उदाहरणों के बीच मजबूत संदर्भ चक्र देखें। प्रोटोकॉल को केवल वर्ग के रूप में चिह्नित करना बाद में आपको यह घोषित करने की अनुमति देगा कि प्रतिनिधि को एक कमजोर संदर्भ का उपयोग करना चाहिए। आप किसी भी कक्षा से केवल प्रोटोकॉल के रूप में चिह्नित करते हैं , AnyObject से विरासत में मिला है , जैसा कि कक्षा-केवल प्रोटोकॉल में चर्चा की गई है।

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID276


7
दिलचस्प। क्या classस्विफ्ट 4.1 में पदावनत है?
होह

@hnh आप अभी भी इसे एक वर्ग बनाकर "छद्म-प्रोटोकॉल" बना सकते हैं, लेकिन प्रोटोकॉल: AnyObject बिल्कुल वही करता है जो ओपी इसे कक्षा बनाने की तुलना में कम दुष्प्रभावों के साथ पूछ रहा है। (आप अभी भी इस तरह के प्रोटोकॉल का उपयोग मूल्य प्रकारों के साथ नहीं कर सकते हैं, लेकिन इसे एक वर्ग घोषित करने से इसका समाधान नहीं होगा)
Arru

8

अपडेट: ऐसा लगता है कि मैनुअल को अपडेट कर दिया गया है और मैं जिस उदाहरण का जिक्र कर रहा हूं उसे हटा दिया गया है। ऊपर @ flainez के उत्तर को संपादित देखें।

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


जैसा कि यह उल्लेख किया गया है IMO प्रश्न का उत्तर नहीं है। एक सादा स्विफ्ट प्रोग्राम एनएसडब्ल्यूवाद से बंधा होने के कारण स्वयं w / o पर खड़ा होने में सक्षम होना चाहिए (यह प्रतिनिधि के अब और कुछ अन्य डिजाइन निर्माण का उपयोग नहीं कर सकता है)। मेरा शुद्ध स्विफ्ट MyClass वास्तव में परवाह नहीं करता है कि गंतव्य एक संरचना या वस्तु है, न ही मुझे वैकल्पिक की आवश्यकता है। हो सकता है कि बाद में उन्हें ठीक करना पड़े, यह एक नई भाषा है। यदि संदर्भ शब्दार्थ की आवश्यकता हो तो संभवतः 'क्लास प्रोटोकॉल XYZ' जैसा कुछ?
होन

4
मुझे लगता है कि यह भी ध्यान देने योग्य है कि \ @objc के अतिरिक्त दुष्प्रभाव हैं - @eXerateed का NSObjectProtocol सुझाव थोड़ा बेहतर है। \ @Objc के साथ - यदि वर्ग प्रतिनिधि एक ऑब्जेक्ट तर्क लेता है, जैसे 'handleResult (r: MySwiftResultClass)', MySwiftResultClass को अब NSObject से वारिस करना होगा! और संभवतः यह नामस्थान भी नहीं है, आदि, संक्षेप में: \ @objc एक शानदार सुविधा है, न कि भाषा।
होन्ह

मुझे लगता है कि उन्होंने इसका हल निकाल लिया है। अब आप लिखते हैं: प्रोटोकॉल MyClassDelegate: class {}
user3675131

इस पर प्रलेखन कहाँ है? या तो मैं अंधा हूं या कुछ गलत कर रहा हूं, क्योंकि मुझे इस बारे में कोई जानकारी नहीं मिल सकती ... O_O
BastiBen

मुझे यकीन नहीं है कि यह ओपी के सवाल का जवाब देता है या नहीं, लेकिन यह विशेष रूप से उपयोगी है यदि आप ओबजैक-सी के साथ इंटरऑपरेट कर रहे हैं;)
दान रोसेनस्टार्क

-1

प्रोटोकॉल AnyObject, वर्ग का उप-वर्ग होना चाहिए

उदाहरण नीचे दिया गया है

    protocol NameOfProtocol: class {
   // member of protocol
    }
   class ClassName: UIViewController {
      weak var delegate: NameOfProtocol? 
    }

-9

Apple "क्लास" के बजाय "NSObjectProtocol" का उपयोग करता है।

public protocol UIScrollViewDelegate : NSObjectProtocol {
   ...
}

यह मेरे लिए भी काम करता है और अपने स्वयं के प्रतिनिधि पैटर्न को लागू करने की कोशिश कर रहे त्रुटियों को हटा दिया।


5
प्रश्न के लिए प्रासंगिक नहीं है, यह सवाल एक शुद्ध स्विफ्ट वर्ग (विशेष रूप से कोई NSObject) के निर्माण के बारे में है जो एक प्रतिनिधि वस्तु का समर्थन करता है। यह उद्देश्य-सी प्रोटोकॉल को लागू करने के बारे में नहीं है, जो आप कर रहे हैं। बाद के लिए @objc उर्फ ​​NSObjectProtocol की आवश्यकता होती है।
होन

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