क्लास अपने सुपरक्लास के आवश्यक सदस्यों को लागू नहीं करता है


155

इसलिए मैंने आज Xcode 6 बीटा 5 को अपडेट किया और देखा कि मुझे Apple की कक्षाओं के लगभग सभी उपवर्गों में त्रुटियां मिलीं।

त्रुटि बताती है:

क्लास 'x' अपने सुपरक्लास के आवश्यक सदस्यों को लागू नहीं करता है

यहाँ एक उदाहरण मैंने उठाया है क्योंकि यह वर्ग वर्तमान में काफी हल्का है इसलिए इसे पोस्ट करना आसान होगा।

class InfoBar: SKSpriteNode  { //Error message here

    let team: Team
    let healthBar: SKSpriteNode

    init(team: Team, size: CGSize) {
        self.team = team
        if self.team == Team.TeamGood {
            healthBar = SKSpriteNode(color: UIColor.greenColor(), size:size)
        }
        else {
            healthBar = SKSpriteNode(color: UIColor.redColor(), size:size)
        }
        super.init(texture:nil, color: UIColor.darkGrayColor(), size: size)

        self.addChild(healthBar)

    }

}

तो मेरा सवाल यह है कि मुझे यह त्रुटि क्यों मिल रही है, और मैं इसे कैसे ठीक कर सकता हूं? ऐसा क्या है जो मैं लागू नहीं कर रहा हूं? मैं एक नामित इनिशियलाइज़र को बुला रहा हूँ।

जवाबों:


127

डेवलपर फ़ोरम पर एक Apple कर्मचारी से:

"कंपाइलर और निर्मित प्रोग्राम को घोषित करने का एक तरीका जिसे आप वास्तव में एनएसकोडिंग-संगत नहीं करना चाहते हैं, कुछ ऐसा करना है:"

required init(coder: NSCoder) {
  fatalError("NSCoding not supported")
}

यदि आप जानते हैं कि आप NSCoding के अनुरूप नहीं होना चाहते हैं, तो यह एक विकल्प है। मैंने अपने SpriteKit कोड के साथ यह दृष्टिकोण लिया है, क्योंकि मुझे पता है कि मैं इसे स्टोरीबोर्ड से लोड नहीं कर रहा हूं।


एक अन्य विकल्प जो आप काम कर सकते हैं, वह यह है कि विधि को सुविधा के रूप में लागू किया जाए, जैसे:

convenience required init(coder: NSCoder) {
    self.init(stringParam: "", intParam: 5)
}

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


कोर्स का तीसरा विकल्प सुपर को कॉल करते समय विधि को लागू करना है, और अपने सभी गैर-वैकल्पिक गुणों को प्रारंभ करना है। यदि ऑब्जेक्ट एक स्टोरीबोर्ड से लोड किया जा रहा है, तो आपको यह दृष्टिकोण लेना चाहिए:

required init(coder aDecoder: NSCoder!) {
    foo = "some string"
    bar = 9001

    super.init(coder: aDecoder)
}

3
दूसरा विकल्प अधिकांश वास्तविक जीवन के मामलों में बेकार है, हालांकि। उदाहरण के लिए, मेरे आवश्यक इनिशलाइज़र को ही लें init(collection:MPMediaItemCollection)। आपको एक वास्तविक मीडिया आइटम संग्रह की आपूर्ति करनी चाहिए; यह इस वर्ग की बात है। यह वर्ग केवल एक के बिना त्वरित नहीं किया जा सकता है। यह संग्रह का विश्लेषण करने और एक दर्जन उदाहरण चर शुरू करने जा रहा है। यही कारण है कि यह केवल और केवल शुरुआती इनिशियलाइज़र है! इस प्रकार, init(coder:)यहाँ आपूर्ति करने के लिए कोई सार्थक (या यहां तक ​​कि अर्थहीन) MPMediaItemCollection नहीं है; केवल fatalErrorदृष्टिकोण ही सही है।
मैट

@matt सही, एक या दूसरा विकल्प विभिन्न परिस्थितियों में बेहतर काम करेगा।
बेन केन

सही, और मैंने स्वतंत्र रूप से दूसरे विकल्प की खोज और विचार किया, और कभी-कभी यह समझ में आएगा। उदाहरण के लिए मैं अपना डिक् घोषित कर सकता था init(collection:MPMediaItemCollection!)। यह init(coder:)शून्य को पारित करने की अनुमति देगा । लेकिन तब मुझे एहसास हुआ: नहीं, अब आप केवल कंपाइलर को बेवकूफ बना रहे हैं। निलिंग पास करना स्वीकार्य नहीं है, इसलिए इसे फेंक दें fatalErrorऔर आगे बढ़ें। :)
मैट

1
मुझे पता है कि यह प्रश्न और इसके उत्तर पुराने तरह के हैं, लेकिन मैंने एक नया उत्तर पोस्ट किया है जो कुछ बिंदुओं को संबोधित करता है जो मुझे लगता है कि वास्तव में इस त्रुटि को समझने के लिए महत्वपूर्ण हैं जो कि किसी भी मौजूदा उत्तर द्वारा संबोधित नहीं किए गए थे।
nhgrif

अच्छा उत्तर। मैं आपसे सहमत हूं कि स्विफ्ट हमेशा सुपर इनिशियलाइज़र्स को विरासत में नहीं देती है, इस पैटर्न को समझना आवश्यक है।
बेन केन

71

स्विफ्ट-विशिष्ट जानकारी के दो बिल्कुल महत्वपूर्ण टुकड़े हैं जो मौजूदा उत्तरों से गायब हैं जो मुझे लगता है कि इसे पूरी तरह से स्पष्ट करने में मदद करते हैं।

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

Tl; डॉ यह है:

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

केवल इनिशियलाइज़र, यदि कोई हो, जिसे आप इनहेरिट करेंगे, सुपर क्लास सुविधा इनिशियलाइज़र हैं जो एक निर्दिष्ट इनिशियलाइज़र को इंगित करते हैं जिसे आपने ओवरराइड किया था।

तो ... लंबे संस्करण के लिए तैयार हैं?


स्विफ्ट में initविधियों के संबंध में विरासत नियमों का एक विशेष सेट है ।

मुझे पता है कि यह मेरे द्वारा बनाए गए दो बिंदुओं में से दूसरा था, लेकिन हम पहले बिंदु को नहीं समझ सकते, या requiredजब तक हम इस बिंदु को नहीं समझते तब तक कीवर्ड क्यों मौजूद है। एक बार जब हम इस बिंदु को समझ जाते हैं, तो दूसरा स्पष्ट हो जाता है।

इस उत्तर के इस भाग में मेरे द्वारा कवर की गई सभी जानकारी Apple के प्रलेखन से मिली है

Apple डॉक्स से:

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

जोर मेरा।

तो, Apple डॉक्स से सीधे वहीं, हम देखते हैं कि स्विफ्ट उपवर्ग हमेशा (और आमतौर पर नहीं) उनके सुपरक्लास के initतरीकों को विरासत में नहीं मिलेगा ।

तो, वे अपने सुपरक्लास से कब विरासत में लेते हैं?

दो नियम हैं जो परिभाषित करते हैं कि एक उपवर्ग initअपने माता-पिता से विधियां प्राप्त करता है। Apple डॉक्स से:

नियम 1

यदि आपका उपवर्ग किसी निर्दिष्ट आरंभीकृत को परिभाषित नहीं करता है, तो यह स्वचालित रूप से अपने सभी सुपरक्लास नामित आरंभिकों को विरासत में देता है।

नियम २

यदि आपका उपवर्ग अपने सभी सुपरक्लास नामित इनिशियलाइज़र के कार्यान्वयन को प्रदान करता है - या तो उन्हें नियम 1 के अनुसार विरासत में मिलता है, या अपनी परिभाषा के भाग के रूप में एक कस्टम कार्यान्वयन प्रदान करता है - तो यह स्वचालित रूप से सभी सुपरक्लास सुविधा इनिशियलाइज़र को विरासत में मिलती है।

नियम 2 क्योंकि इस बातचीत के लिए विशेष रूप से प्रासंगिक नहीं है SKSpriteNodeके init(coder: NSCoder)लिए एक सुविधा विधि होने की संभावना नहीं है।

इसलिए, आपकी InfoBarकक्षा को requiredप्रारंभिक बिंदु विरासत में मिला था , जब तक कि आपने जो बिंदु नहीं जोड़ा था init(team: Team, size: CGSize)

तुम थे इस प्रदान नहीं किया है करने के लिए, तो initविधि और इसके बजाय अपने किए गए InfoBar's को जोड़ा गया गुण वैकल्पिक या मूलभूत मूल्यों के साथ उन्हें प्रदान की है, तो आप अब भी विरासत में दिया है चाहता हूँ SKSpriteNode' s init(coder: NSCoder)। हालाँकि, जब हमने अपने कस्टम इनिशियलाइज़र को जोड़ा, तो हमने अपने सुपरक्लास के नामित इनिशियलाइज़र (और सुविधा इनिशियलाइज़र जो हमने लागू किया इनिशियलाइज़र्स को इंगित नहीं किया था) को विरासत में देना बंद कर दिया ।

इसलिए, एक सरल उदाहरण के रूप में, मैं इसे प्रस्तुत करता हूं:

class Foo {
    var foo: String
    init(foo: String) {
        self.foo = foo
    }
}

class Bar: Foo {
    var bar: String
    init(foo: String, bar: String) {
        self.bar = bar
        super.init(foo: foo)
    }
}


let x = Bar(foo: "Foo")

जो निम्नलिखित त्रुटि प्रस्तुत करता है:

कॉल में पैरामीटर 'बार' के लिए लापता तर्क।

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

यदि यह उद्देश्य-सी होते हैं, तो इसे विरासत में कोई समस्या नहीं होगी। यदि हमने ऑब्जेक्टिव-सी के Barसाथ इनिशियलाइज़ किया initWithFoo:, तो self.barसंपत्ति बस होगी nil। यह शायद महान नहीं है, लेकिन यह एक पूरी तरह से है मान्य के लिए वस्तु में होने की राज्य। यह नहीं के लिए स्विफ्ट वस्तु में होने के लिए एक पूरी तरह से वैध राज्य। self.barएक वैकल्पिक नहीं है और नहीं किया जा सकता nil

फिर से, हमें इनिशियलाइज़र्स का एकमात्र तरीका विरासत में मिला है, जो हमें स्वयं प्रदान नहीं करता है। इसलिए यदि हम हटाने Barकी कोशिश करते हैं init(foo: String, bar: String), जैसे कि:

class Bar: Foo {
    var bar: String
}

अब हम विरासत में वापस आ रहे हैं (प्रकार), लेकिन यह संकलित नहीं करेगा ... और त्रुटि संदेश ठीक यही बताता है कि हमें अधिवास initविधि क्यों नहीं मिली :

समस्या: कक्षा 'बार' का कोई आरंभक नहीं है

फिक्स-इट: स्टैरिअलाइज़र्स के बिना संग्रहीत प्रॉपर्टी 'बार' संश्लेषित इनिशियलाइज़र को रोकता है

यदि हमने अपने उपवर्ग में संग्रहीत संपत्तियाँ जोड़ी हैं, तो सुपरक्लास इनिशियलाइज़र के साथ हमारे उपवर्ग का एक वैध उदाहरण बनाने के लिए कोई संभव स्विफ्ट तरीका नहीं है जो संभवतः हमारे उपवर्ग के संग्रहीत गुणों के बारे में नहीं जान सकता है।


ठीक है, ठीक है, मुझे क्यों लागू init(coder: NSCoder)करना है? क्यों है required?

स्विफ्ट के initतरीके विरासत नियमों के एक विशेष सेट द्वारा खेल सकते हैं, लेकिन प्रोटोकॉल अनुरूपता अभी भी श्रृंखला के नीचे विरासत में मिली है। यदि कोई मूल वर्ग किसी प्रोटोकॉल के अनुरूप है, तो उसके उपवर्गों को उस प्रोटोकॉल के अनुरूप होना चाहिए।

आमतौर पर, यह एक समस्या नहीं है, क्योंकि अधिकांश प्रोटोकॉल के लिए केवल उन विधियों की आवश्यकता होती है, जो स्विफ्ट में विशेष विरासत नियमों द्वारा नहीं खेलती हैं, इसलिए यदि आप एक वर्ग से विरासत में प्राप्त कर रहे हैं जो एक प्रोटोकॉल के अनुरूप है, तो आप सभी को भी विरासत में मिला रहे हैं तरीके या गुण जो वर्ग को प्रोटोकॉल अनुरूपता को पूरा करने की अनुमति देते हैं।

हालांकि, याद रखें, स्विफ्ट के initतरीके नियमों के एक विशेष सेट द्वारा खेलते हैं और हमेशा विरासत में नहीं मिलते हैं। इस वजह से, एक वर्ग जो एक प्रोटोकॉल के अनुरूप होता है जिसे विशेष initविधियों (जैसे NSCoding) की आवश्यकता होती है, वर्ग को उन initतरीकों को चिह्नित करना होता है required

इस उदाहरण पर विचार करें:

protocol InitProtocol {
    init(foo: Int)
}

class ConformingClass: InitProtocol {
    var foo: Int
    init(foo: Int) {
        self.foo = foo
    }
}

यह संकलन नहीं है। यह निम्नलिखित चेतावनी उत्पन्न करता है:

समस्या: प्रारंभिक आवश्यकता 'init (foo :)' को केवल गैर-अंतिम वर्ग 'कॉनफ़ॉर्मिंगक्लास' में 'आवश्यक' इनिशियलाइज़र द्वारा संतुष्ट किया जा सकता है

फिक्स-इट: आवश्यक सम्मिलित करें

यह मुझे init(foo: Int)इनिशियलाइज़र को आवश्यक बनाने के लिए चाहता है । मैं वर्ग को खुश करके भी खुश कर सकता था final(मतलब वर्ग को विरासत में नहीं मिला जा सकता है)।

तो, क्या होगा अगर मैं उपवर्ग? इस बिंदु से, अगर मैं उपवर्ग करता हूं, तो मैं ठीक हूं। यदि मैं किसी भी इनिशियलाइज़र को जोड़ता हूं, तो मैं अचानक विरासत में नहीं हूं init(foo:)। यह समस्याग्रस्त है क्योंकि अब मैं इसके अनुरूप नहीं हूं InitProtocol। मैं उस वर्ग से उपवर्ग नहीं कर सकता, जो किसी प्रोटोकॉल के अनुरूप है और फिर अचानक तय करता है कि मैं अब उस प्रोटोकॉल के अनुरूप नहीं होना चाहता। मुझे प्रोटोकॉल अनुरूपता विरासत में मिली है, लेकिन स्विफ्ट जिस तरह से initविधि वंशानुक्रम के साथ काम करता है , मुझे उस प्रोटोकॉल के अनुरूप होने के लिए आवश्यक हिस्सा विरासत में नहीं मिला है और मुझे इसे लागू करना चाहिए।


ठीक है, यह सब समझ में आता है। लेकिन मुझे अधिक उपयोगी त्रुटि संदेश क्यों नहीं मिल सकता है?

तर्क से, त्रुटि संदेश अधिक स्पष्ट या बेहतर हो सकता है यदि यह निर्दिष्ट करता है कि आपकी कक्षा विरासत में प्राप्त NSCodingप्रोटोकॉल के अनुरूप नहीं थी और इसे ठीक करने के लिए आपको इसे लागू करने की आवश्यकता है init(coder: NSCoder)। ज़रूर।

लेकिन Xcode बस उस संदेश को उत्पन्न नहीं कर सकता है क्योंकि यह वास्तव में हमेशा आवश्यक समस्या को लागू करने या विरासत में नहीं लेने के साथ वास्तविक समस्या होगी। प्रोटोकॉल के अनुरूप initतरीके बनाने के लिए कम से कम एक और कारण है required, और वह है कारखाने के तरीके।

यदि मैं एक उचित कारखाना विधि लिखना चाहता हूं, तो मुझे रिटर्न प्रकार Self(ऑब्जेक्ट-सी के स्विफ्ट के समकक्ष instanceType) को निर्दिष्ट करने की आवश्यकता है । लेकिन ऐसा करने के लिए, मुझे वास्तव में एक requiredशुरुआती विधि का उपयोग करने की आवश्यकता है ।

class Box {
    var size: CGSize
    init(size: CGSize) {
        self.size = size
    }

    class func factory() -> Self {
        return self.init(size: CGSizeZero)
    }
}

यह त्रुटि उत्पन्न करता है:

एक मेटाटाइप मान के साथ वर्ग प्रकार 'सेल्फ' के ऑब्जेक्ट का निर्माण एक 'आवश्यक' इनिशियलाइज़र का उपयोग करना चाहिए

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

यह मूल रूप से एक ही समस्या है। यदि हम उपवर्ग करते हैं Box, तो हमारे उपवर्ग वर्ग विधि को विरासत में देंगे factory। तो हम कॉल कर सकते थे SubclassedBox.factory()। हालांकि, बिना requiredपर कीवर्ड init(size:)विधि, Boxके उपवर्गों के वारिस की गारंटी नहीं दी self.init(size:)है कि factoryबुला रहा है।

इसलिए हमें इस विधि को बनाना चाहिए requiredअगर हम इस तरह का कारखाना तरीका चाहते हैं, और इसका मतलब है कि यदि हमारी कक्षा इस तरह की विधि लागू करती है, तो हमारे पास एक requiredप्रारंभिक विधि होगी और हम आपके द्वारा यहां चलाई गई ठीक उसी समस्याओं में भाग लेंगे NSCodingप्रोटोकॉल के साथ ।


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

हालांकि यहां मुख्य बिंदु यह है कि यदि हम आपको यहां दिखाई देने वाली त्रुटि प्राप्त कर रहे हैं, तो इसका मतलब है कि आपकी कक्षा वास्तव में विधि को लागू नहीं कर रही है।

जैसा कि शायद एक अंतिम उदाहरण इस तथ्य में ड्रिल करने के लिए है कि स्विफ्ट उपवर्ग हमेशा अपने माता-पिता के initतरीकों को विरासत में नहीं लेते हैं (जो मुझे लगता है कि इस समस्या को पूरी तरह से समझने के लिए बिल्कुल केंद्रीय है), इस उदाहरण पर विचार करें:

class Foo {
    init(a: Int, b: Int, c: Int) {
        // do nothing
    }
}

class Bar: Foo {
    init(string: String) {
        super.init(a: 0, b: 1, c: 2)
        // do more nothing
    }
}

let f = Foo(a: 0, b: 1, c: 2)
let b = Bar(a: 0, b: 1, c: 2)

यह संकलन करने में विफल रहता है।

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

त्रुटि संदेश जो देता है वह थोड़ा भ्रामक है:

कॉल में अतिरिक्त तर्क 'बी'

लेकिन बिंदु, है Barमें से किसी के वारिस नहीं है Fooके initतरीकों, क्योंकि यह दो विशेष मामलों में से किसी इनहेरिट के लिए पूरी नहीं की initअपनी मूल वर्ग से तरीकों।

यदि यह ऑब्जेक्टिव-सी थे, तो हमें initकोई समस्या नहीं होगी, क्योंकि ऑब्जेक्टिव-सी ऑब्जेक्ट्स की प्रॉपर्टीज़ को इनिशियलाइज़ नहीं करने से पूरी तरह खुश है (हालाँकि एक डेवलपर के रूप में, आपको इससे खुश नहीं होना चाहिए)। स्विफ्ट में, यह बस नहीं चलेगा। आपके पास एक अमान्य स्थिति नहीं हो सकती है, और सुपरक्लास इनिशियलाइज़र को विरासत में प्राप्त करने से केवल अमान्य ऑब्जेक्ट स्थिति हो सकती है।


क्या आप कृपया बता सकते हैं कि इस वाक्य का क्या अर्थ है या एक उदाहरण दें? "(सुविधा और इनिशियलाइज़र जो हमने इनिशियलाइज़र्स को लागू नहीं किया था)"
अभय जैक्सन

शानदार जवाब! मैं और अधिक चाहते हैं अतः पदों के बारे में हो सकता है क्यों , यह एक, केवल के बजाय की तरह कैसे
अलेक्जेंडर वासिनिन

56

यह मुद्दा क्यों उठा है? ठीक है, स्पष्ट तथ्य यह है कि यह हमेशा महत्वपूर्ण रहा है (यानी ऑब्जेक्टिव-सी में, जब से मैंने मैक ओएस एक्स 10.0 में कोको को वापस लाना शुरू किया है) शुरुआती लोगों से निपटने के लिए कि आपकी कक्षा को संभालने के लिए तैयार नहीं है। डॉक्स इस संबंध में आपकी जिम्मेदारियों के बारे में हमेशा स्पष्ट रहे हैं। लेकिन हममें से कितने लोगों ने उन्हें, पूरी तरह से और पत्र को पूरा करने के लिए परेशान किया? शायद हममें से कोई नहीं! और संकलक ने उन्हें लागू नहीं किया; यह सब विशुद्ध रूप से पारंपरिक था।

उदाहरण के लिए, मेरे ऑब्जेक्ट-सी व्यू कंट्रोलर में इस निर्दिष्ट इनिशियलाइज़र के साथ उपवर्ग:

- (instancetype) initWithCollection: (MPMediaItemCollection*) coll;

... यह महत्वपूर्ण है कि हमें एक वास्तविक मीडिया आइटम संग्रह पारित किया जाए: उदाहरण केवल एक के बिना अस्तित्व में नहीं आ सकता है। लेकिन मैंने किसी को रोकने के लिए कोई "डाट" नहीं लिखा है, initइसके बजाय मुझे नंगे-हड्डियों के साथ शुरू करने से रोकें । मुझे एक लिखना चाहिए था (वास्तव में, ठीक से बोल रहा हूं, मुझे एक कार्यान्वयन initWithNibName:bundle:, विरासत में मिला नामित आरंभकर्ता लिखना चाहिए था); लेकिन मैं परेशान होने के लिए बहुत आलसी था, क्योंकि मुझे पता था कि मैं गलत तरीके से अपनी कक्षा को इस तरह से शुरू नहीं करूंगा। इसने एक अंतराल छेद छोड़ दिया। ऑब्जेक्टिव-सी में, कोई व्यक्ति नंगे-हड्डियों को बुला सकता हैinit , जिससे मेरा हाथी अनियंत्रित हो जाएगा, और हम पैडल के बिना क्रीक कर सकते हैं।

आश्चर्यजनक रूप से, स्विफ्ट, मुझे ज्यादातर मामलों में खुद से बचाता है। जैसे ही मैंने इस ऐप का स्विफ्ट में अनुवाद किया, सारी समस्या दूर हो गई। प्रभावी ढंग से स्विफ्ट मेरे लिए एक डाट बनाता है! यदि init(collection:MPMediaItemCollection)मेरी कक्षा में एकमात्र निर्दिष्ट इनिशियलाइज़र घोषित किया गया है, तो मुझे नंगे-हड्डियों को बुलाकर इनिशियलाइज़ नहीं किया जा सकता है init()। यह एक चमत्कार है!

बीज 5 में जो हुआ है वह केवल यह है कि संकलक ने महसूस किया है कि चमत्कार के मामले में काम नहीं करता है init(coder:), क्योंकि सिद्धांत रूप में इस वर्ग का एक उदाहरण एक नीब से आ सकता है, और संकलक को रोक नहीं सकता है - और जब nib भार, init(coder:)कहा जाएगा। इसलिए संकलक आपको स्टॉपर को स्पष्ट रूप से लिखता है। और काफी सही भी।


ऐसे विस्तृत उत्तर के लिए धन्यवाद। यह वास्तव में मामले में प्रकाश लाता है।
जूलियन ओसोरियो

कंपाइलर को बंद करने के तरीके के बारे में बताने के लिए पास्ता 12 तक का अपवॉट, लेकिन आपको यह बताने के लिए एक अपवोट भी है कि पहली बार में यह क्या था।
गैरेट अलब्राइट

2
छेद में छेद करना या न होना, मैं कभी इस जड़ता को कहने वाला नहीं था, इसलिए मुझे इसे शामिल करने के लिए मजबूर करना पूरी तरह से अपमानजनक है। ब्लोटेड कोड एक ओवरहेड है जिसकी हममें से किसी को जरूरत नहीं है। यह अब आपको दोनों गुणों के साथ-साथ अपने गुणों को शुरू करने के लिए भी मजबूर करता है। व्यर्थ!
डैन ग्रीनफील्ड

5
@DanGreenfield नहीं, यह तुम कुछ भी प्रारंभ करने में, क्योंकि यदि आप यह कभी नहीं कॉल करने के लिए आप बस में डाल जा रहे हैं के लिए मजबूर नहीं करता fatalErrorडाट में वर्णित stackoverflow.com/a/25128815/341994 । बस इसे एक उपयोगकर्ता कोड स्निपेट बनाएं और अब से आप इसे केवल वहीं खोल सकते हैं जहां इसकी आवश्यकता है। आधा सेकेंड लेता है।
मैट

1
@ होफ्रीग खैर, निष्पक्ष होने के लिए, सवाल पूरी कहानी के लिए नहीं पूछा गया। बस इस जाम से बाहर निकलने और आगे बढ़ने के बारे में था। पूरी कहानी मेरी पुस्तक में दी गई है: apeth.com/swiftBook/ch04.html#_class_initializers
मैट

33

जोड़ना

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

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

1
हाँ! मुझे यह कहते हुए जल्द ही एहसास हुआ कि यह एक बग हो सकता है, कि यह वास्तव में तार्किक समझ में आता है। मैं मानता हूं कि यह बहुत सारे व्यर्थ कोड होंगे, क्योंकि आप जैसे मैं इस init पद्धति का उपयोग कभी नहीं करूंगा। अभी तक एक सुंदर समाधान के बारे में निश्चित नहीं है
गगन सिंह 20

2
मेरी भी यही समस्या थी। यह "आवश्यक init" के साथ समझ में आता है, लेकिन स्विफ्ट "आसान" भाषा नहीं है जिसकी मुझे उम्मीद थी। ये सभी "वैकल्पिक" भाषा को आवश्यकता से अधिक जटिल बना रहे हैं। और DSL और AOP के लिए कोई समर्थन नहीं। मैं ज्यादा से ज्यादा निराश हो रहा हूं।
user810395

2
हां मैं पूरी तरह से सहमत हूं। मेरे गुणों को अब वैकल्पिक के रूप में घोषित किया गया है क्योंकि मैं इसे करने के लिए मजबूर हूं, जब वास्तव में उन्हें शून्य होने की अनुमति नहीं दी जानी चाहिए। कुछ वैकल्पिक हैं क्योंकि वे वैध रूप से वैकल्पिक होना चाहिए (जिसका अर्थ है कि शून्य एक वैध मूल्य है)। और फिर उन कक्षाओं में जहां मैं उप-वर्ग नहीं कर रहा हूं मुझे वैकल्पिक उपयोग करने की आवश्यकता नहीं है, इसलिए चीजें बहुत जटिल हो रही हैं, और मुझे एक सही कोडिंग शैली नहीं मिल सकती है। उम्मीद है कि Apple कुछ समझ पाए।
एपिक बाइट

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