वास्तव में init कोडर aDecoder क्या है?


122

मैं एक ऑनलाइन कोर्स से आईओएस विकास सीख रहा हूं और हर बार मैं एक कस्टम व्यू (कस्टम टेबल व्यू सेल, कलेक्शन व्यू सेल आदि) करता हूं। इंस्ट्रक्टर हमेशा इस इनिशियलाइज़र को लागू करता है:

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

क्यों मुझे हमेशा यह फोन करना पड़ता है? यह क्या करता है? क्या मैं इनिट के अंदर गुण डाल सकता हूं?


5
यह जवाब आपको stackoverflow.com/questions/24036393/… पर मदद करेगा
Seungyoun Yi

2
यदि आप उस ऑब्जेक्ट को उपवर्गित करते हैं जो लागू होता है, NSCodingतो आपको इस इनिशियलाइज़र को लागू करने की आवश्यकता है, क्योंकि इसे लागू करने वाली कक्षाओं की आवश्यकता होती है NSCoding। आपको कम से कम सुपरक्लास इनिट विधि को कॉल करना होगा। यदि NSCoderआपकी कक्षा के लिए एन्कोडेड गुण हैं, तो आप उन्हें पुनर्प्राप्त करने के लिए इस विधि का उपयोग कर सकते हैं
पॉलव 11

1
इसके अलावा, मैं आपको Apple द्वारा आधिकारिक स्विफ्ट बुक में ऑब्जेक्ट इंटिग्रेशन के बारे में अनुभाग पढ़ने की सलाह देता हूं।
निकोलस मियारी

जवाबों:


121

मैं इस उत्तर को विपरीत दिशा से शुरू करूंगा: यदि आप डिस्क पर अपने दृश्य की स्थिति को सहेजना चाहते हैं तो क्या होगा? इसे क्रमबद्धता के रूप में जाना जाता है । रिवर्स deserialization है - डिस्क से ऑब्जेक्ट की स्थिति को पुनर्स्थापित करना।

NSCodingप्रोटोकॉल serialize और deserialize वस्तुओं के लिए दो तरीकों को परिभाषित करता है:

encodeWithCoder(_ aCoder: NSCoder) {
    // Serialize your object here
}

init(coder aDecoder: NSCoder) {
    // Deserialize your object here
}

तो आपके कस्टम वर्ग में इसकी आवश्यकता क्यों है? इसका जवाब है इंटरफ़ेस बिल्डर। जब आप एक स्टोरीबोर्ड पर किसी ऑब्जेक्ट को खींचते हैं और इसे कॉन्फ़िगर करते हैं, तो इंटरफ़ेस बिल्डर डिस्क पर उस ऑब्जेक्ट की स्थिति को क्रमबद्ध करता है, फिर स्टोरीबोर्ड स्क्रीन पर दिखाई देने पर इसे डिसेरिएलाइज़ करता है। आपको इंटरफ़ेस बिल्डर को यह बताने की आवश्यकता है कि उन्हें कैसे करना है। बहुत कम से कम, यदि आप अपने उपवर्ग में कोई नया गुण नहीं जोड़ते हैं, तो आप बस सुपरक्लास को आपके लिए पैकिंग और अनपैकिंग करने के लिए कह सकते हैं, इसलिए super.init(coder: aDecoder)कॉल करें। यदि आपका उपवर्ग अधिक जटिल है, तो आपको उपवर्ग के लिए अपना स्वयं का क्रमांकन और डीरियलाइज़ेशन कोड जोड़ना होगा।

यह विज़ुअल स्टूडियो के दृष्टिकोण के विपरीत है, जो कि रन समय पर ऑब्जेक्ट बनाने के लिए एक छिपे हुए फ़ाइल में कोड लिखना है।


क्यों नहीं सब कुछ awakeFromNib के अंदर डाल दिया और उपयोग भूल गए init(coder aCoder : NSCoder)?
हनी

@ - एक शब्द में, "कभी-कभी आप ऐसा नहीं कर सकते"। आप आम तौर पर कर सकते हैं लेकिन हमेशा नहीं।
फेटी

@ फेटी यह जानना बहुत जटिल या अनावश्यक नहीं है? अगर आपको समझाने का मन नहीं है?
हनी

9
@ यदि आप इंटरफ़ेस बिल्डर में अपनी वस्तु को कॉन्फ़िगर करना चाहते हैं तो awakeFromNibकाम नहीं करेगा। रन टाइमawakeFromNib पर आमंत्रित किया जाता है । इंटरफ़ेस बिल्डर में आप जो कुछ भी करते हैं वह डिज़ाइन समय के दौरान होता है । ले जाने के लिए क्या आप में किया है डिजाइन समय को रन टाइम है (बचत) और (लोड हो रहा है)encodeWithCoderinit(coder:)
कोड अलग

3
@ यदि आप अपने कस्टम वर्ग को कॉन्फ़िगर करने के लिए इंटरफ़ेस बिल्डर का उपयोग नहीं करते हैं (यानी यह प्रोग्राम कोड के साथ करते हैं) तो आप इसे कर सकते हैं awakeFromNibयाinitWIthFrame
कोड अलग-अलग

28

उस आरंभक को लागू करने की आवश्यकता दो चीजों का परिणाम है:

  1. Liskov प्रतिस्थापन सिद्धांत । यदि S, T का उपवर्ग है (जैसे MyViewControllerएक उपवर्ग है ViewController), तो S ऑब्जेक्ट्स (इंस्टेंसेस MyViewController) को प्रतिस्थापित किया जा सकता है जहां T ऑब्जेक्ट्स (इंस्टेंसेस ViewController) अपेक्षित हैं।

  2. यदि कोई आरंभिक उपवर्ग में स्पष्ट रूप से परिभाषित किया गया है, तो स्विफ्ट में विरासत नहीं मिली है। यदि एक इनिशियलाइज़र स्पष्ट रूप से प्रदान किया गया है, तो अन्य सभी को स्पष्ट रूप से प्रदान किया जाना चाहिए (जो तब कॉल कर सकते हैं super.init(...))। इस सवाल को तर्क के लिए देखें । यह जावा में है, लेकिन फिर भी लागू होता है।

बिंदु 1 तक, सब कुछ जो मूल ViewControllerकर सकता है, MyViewControllerउपवर्ग को करने में सक्षम होना चाहिए। इस तरह की एक चीज को किसी दिए से आरंभ किया जा सकता है NSCoder। बिंदु 2 तक, आपका MyViewControllerउपवर्ग स्वचालित रूप से इस क्षमता को प्राप्त नहीं करता है। इस प्रकार, आपको मैन्युअल रूप से इस आवश्यकता को पूरा करने वाले इनिशियलाइज़र की आपूर्ति करनी चाहिए। इस मामले में, आपको बस सुपरक्लास को सौंपने की जरूरत है, यह करने के लिए कि यह आमतौर पर क्या करेगा।


1
यह सही समझ में आता है कि कंस्ट्रक्टरों को विरासत में नहीं मिला है: यदि आप बेस क्लास का (विरासत में मिला) इनिशियलाइज़र का उपयोग करके व्युत्पन्न वर्ग के एक उदाहरण को इनिशियलाइज़ करते हैं, तो गैर-इनहेरिट किए गए गुण जो व्युत्पन्न वर्ग द्वारा नए परिभाषित ("जोड़े गए") कभी नहीं होंगे। प्रारंभिक हो।
निकोलस मिआरी जूल

3
वास्तव में, इनिशियलाइज़र स्विफ्ट में विरासत में मिले हैं, बशर्ते कि आप अपने उपवर्ग में अपना कोई इनिशियलाइज़र लागू न करें। यदि आपके नए परिभाषित गैर-विरासत वाले गुणों में डिफ़ॉल्ट मान हैं, तो आप अपने उपवर्ग में कोई भी इनिशियलाइज़र नहीं लिखने के साथ दूर हो सकते हैं और बस अपने सभी सुपरक्लास के इनिशियलाइज़र को प्राप्त कर सकते हैं। यहां
TheBaj
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.