क्या है "घातक त्रुटि: एक वैकल्पिक मूल्य को उजागर करते समय अप्रत्याशित रूप से शून्य पाया जाता है" का मतलब है?


415

मेरा स्विफ्ट कार्यक्रम EXC_BAD_INSTRUCTIONनिम्नलिखित समान त्रुटियों में से एक के साथ दुर्घटनाग्रस्त हो रहा है । इस त्रुटि का क्या अर्थ है, और मैं इसे कैसे ठीक करूं?

घातक त्रुटि: वैकल्पिक मूल्य को खोलते समय अप्रत्याशित रूप से शून्य पाया गया

या

घातक त्रुटि: एक वैकल्पिक मान को स्पष्ट करते हुए अप्रत्याशित रूप से शून्य पाया गया


इस पोस्ट का उद्देश्य "अप्रत्याशित रूप से पाए गए शून्य" मुद्दों के उत्तर एकत्र करना है, ताकि वे बिखरे हुए और खोजने में कठिन न हों। अपने स्वयं के उत्तर को जोड़ने या मौजूदा विकी उत्तर को संपादित करने के लिए स्वतंत्र महसूस करें ।


8
@RobertColumbia, यह एक कम्युनिटी विकी क्यू एंड ए जोड़ी है जिसके पास व्यापक मुद्दे के दस्तावेज हैं, मुझे नहीं लगता कि इस सवाल को MCVE की कमी के लिए बंद किया जाना चाहिए।
जाल

इस तरह से वैरिएबल बनाएं [var nameOfDaughter: String? ] और इस तरह के चर का उपयोग करें [अगर _ = nameOfDaughter {}] सबसे अच्छा तरीका है।
iOS

जवाबों:


673

यह उत्तर सामुदायिक विकि है । यदि आपको लगता है कि इसे बेहतर बनाया जा सकता है, तो इसे संपादित करने के लिए स्वतंत्र महसूस करें !

पृष्ठभूमि: एक वैकल्पिक क्या है?

स्विफ्ट में, Optionalएक सामान्य प्रकार है जिसमें किसी भी प्रकार का मान (या किसी भी प्रकार का) हो सकता है।

कई अन्य प्रोग्रामिंग भाषाओं में, एक विशेष "प्रहरी" मूल्य का उपयोग अक्सर मूल्य की कमी को इंगित करने के लिए किया जाता है । उद्देश्य-सी में, उदाहरण के लिए, nil( अशक्त सूचक ) किसी वस्तु की कमी को दर्शाता है। लेकिन यह और अधिक मुश्किल हो जाता है जब आदिम प्रकारों के साथ काम करना - -1पूर्णांक की अनुपस्थिति को इंगित करने के लिए उपयोग किया जाना चाहिए , या शायद INT_MIN, या कुछ पूर्णांक? यदि किसी विशेष मूल्य को "नो पूर्णांक" के लिए चुना जाता है, तो इसका मतलब है कि इसे अब वैध मान के रूप में नहीं माना जा सकता है ।

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

स्विफ्ट में, किसी भी प्रकार को वैकल्पिक बनाया जा सकता है । एक वैकल्पिक मूल्य मूल प्रकार, या विशेष मूल्य से किसी भी मूल्य पर ले सकता है nil

वैकल्पिक ?प्रकार पर एक प्रत्यय के साथ परिभाषित किया गया है:

var anInt: Int = 42
var anOptionalInt: Int? = 42
var anotherOptionalInt: Int?    // `nil` is the default when no value is provided

एक वैकल्पिक में एक मूल्य की कमी से संकेत मिलता है nil:

anOptionalInt = nil

(ध्यान दें कि यह ऑब्जेक्टिव-सी में nilसमान नहीं nilहै। ऑब्जेक्टिव-सी में, ऑब्जेक्ट ऑब्जेक्ट पॉइंटरnil की अनुपस्थिति है , स्विफ्ट में, ऑब्जेक्ट्स / रेफरेंस टाइप्स के लिए ऑप्शनल को प्रतिबंधित नहीं किया जाता है। ऑप्शनल हील की शायद इसी तरह का व्यवहार करता है ।)


मुझे एक वैकल्पिक मूल्य को उजागर करते समय " घातक त्रुटि: अप्रत्याशित रूप से शून्य क्यों मिला ?"

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

कोड की एक पंक्ति को उजागर करके Xcode आपको दुर्घटना दिखाएगा। इस लाइन पर समस्या होती है।

दुर्घटनाग्रस्त लाइन

यह दुर्घटना दो अलग-अलग प्रकार के फोर्स-अनप्रैप के साथ हो सकती है:

1. स्पष्ट बल खोलना

यह !एक वैकल्पिक पर ऑपरेटर के साथ किया जाता है । उदाहरण के लिए:

let anOptionalString: String?
print(anOptionalString!) // <- CRASH

घातक त्रुटि: वैकल्पिक मूल्य को खोलते समय अप्रत्याशित रूप से शून्य पाया गया

जैसा anOptionalStringकि nilयहां है, आपको उस लाइन पर एक दुर्घटना मिलेगी जहां आप इसे खोलते हैं।

2. अवैध रूप से अनचाहे वैकल्पिक

इन्हें एक प्रकार के !बजाय एक के साथ परिभाषित किया ?गया है।

var optionalDouble: Double!   // this value is implicitly unwrapped wherever it's used

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

print(optionalDouble) // <- CRASH

घातक त्रुटि: एक वैकल्पिक मान को स्पष्ट करते हुए अप्रत्याशित रूप से शून्य पाया गया

यह पता लगाने के लिए कि क्रैश किस चर के कारण हुआ, आप परिभाषा दिखाने के लिए क्लिक करते समय पकड़ सकते हैं , जहाँ आपको वैकल्पिक प्रकार मिल सकता है।

IBOutlets, विशेष रूप से, आमतौर पर अंतर्निहित अलिखित वैकल्पिक हैं। ऐसा इसलिए है क्योंकि आपका xib या स्टोरीबोर्ड प्रारंभ के बाद , रनटाइम पर आउटलेट को लिंक करेगा । इसलिए आपको यह सुनिश्चित करना चाहिए कि आपके द्वारा लोड किए जाने से पहले आप आउटलेट्स तक नहीं पहुंच रहे हैं। आपको यह भी जांचना चाहिए कि कनेक्शन आपके स्टोरीबोर्ड / xib फ़ाइल में सही हैं, अन्यथा मान nilरनटाइम पर होंगे , और इसलिए जब वे निहित होते हैं तो दुर्घटनाग्रस्त हो जाते हैं । कनेक्शन ठीक करते समय, अपने आउटलेट को परिभाषित करने वाले कोड की पंक्तियों को हटाने का प्रयास करें, फिर उन्हें फिर से कनेक्ट करें।


जब मैं कभी भी एक वैकल्पिक खोलना मजबूर करना चाहिए?

स्पष्ट बल खोलना

एक सामान्य नियम के रूप में, आपको स्पष्ट रूप से !ऑपरेटर के साथ एक विकल्प को खोलना कभी भी मजबूर नहीं करना चाहिए । ऐसे मामले हो सकते हैं जहां उपयोग !करना स्वीकार्य है - लेकिन आपको केवल इसका उपयोग करना चाहिए यदि आप 100% सुनिश्चित हैं कि वैकल्पिक में एक मूल्य है।

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

अवैध रूप से अनचाहे वैकल्पिक

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

आपको अंतिम उपाय के रूप में केवल अंतर्निहित अलिखित वैकल्पिक का उपयोग करना चाहिए । यदि आप एक आलसी चर का उपयोग कर सकते हैं , या एक चर के लिए एक डिफ़ॉल्ट मान प्रदान कर सकते हैं - तो आपको एक अंतर्निहित अनपेक्षित वैकल्पिक का उपयोग करने के बजाय ऐसा करना चाहिए।

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


मैं वैकल्पिक रूप से कैसे निपट सकता हूं?

यह जांचने का सबसे सरल तरीका है कि वैकल्पिक में कोई मान है या नहीं, इसकी तुलना करना है nil

if anOptionalInt != nil {
    print("Contains a value!")
} else {
    print("Doesn’t contain a value.")
}

हालांकि, 99.9% समय जब वैकल्पिक के साथ काम करते हैं, तो आप वास्तव में इसके मूल्य को एक्सेस करना चाहते हैं, अगर इसमें एक भी शामिल हो। ऐसा करने के लिए, आप वैकल्पिक बाइंडिंग का उपयोग कर सकते हैं ।

वैकल्पिक बंधन

वैकल्पिक बाइंडिंग आपको यह जांचने की अनुमति देती है कि क्या वैकल्पिक में कोई मान है - और आपको एक नए चर या स्थिर पर अलिखित मान असाइन करने की अनुमति देता है। यह सिंटैक्स का उपयोग करता है if let x = anOptional {...}या if var x = anOptional {...}, यदि आपको इसे बाध्य करने के बाद नए चर के मूल्य को संशोधित करने की आवश्यकता है।

उदाहरण के लिए:

if let number = anOptionalInt {
    print("Contains a value! It is \(number)!")
} else {
    print("Doesn’t contain a number")
}

यह क्या करता है पहले जांचें कि वैकल्पिक में एक मूल्य है। यदि यह करता है , तो 'अलिखित' मान एक नए चर ( number) को सौंपा गया है - जिसे आप तब स्वतंत्र रूप से उपयोग कर सकते हैं जैसे कि यह गैर-वैकल्पिक था। यदि वैकल्पिक में कोई मान नहीं है, तो अन्य क्लॉज़ को लागू किया जाएगा, जैसा कि आप उम्मीद करेंगे।

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

var anOptionalInt : Int?
var anOptionalString : String?

if let number = anOptionalInt, let text = anOptionalString {
    print("anOptionalInt contains a value: \(number). And so does anOptionalString, it’s: \(text)")
} else {
    print("One or more of the optionals don’t contain a value")
}

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

if let number = anOptionalInt, number > 0 {
    print("anOptionalInt contains a value: \(number), and it’s greater than zero!")
}

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

एक गार्ड स्टेटमेंट आपको सफलता के लिए एक शर्त को परिभाषित करने की अनुमति देता है - और वर्तमान स्कोप केवल उस स्थिति को पूरा करने के लिए निष्पादित करना जारी रखेगा। उन्हें वाक्य रचना के साथ परिभाषित किया गया है guard condition else {...}

इसलिए, वैकल्पिक बंधन के साथ उनका उपयोग करने के लिए, आप यह कर सकते हैं:

guard let number = anOptionalInt else {
    return
}

(ध्यान दें कि गार्ड बॉडी के भीतर, आपको वर्तमान में निष्पादित कोड के दायरे से बाहर निकलने के लिए कंट्रोल ट्रांसफर स्टेटमेंट्स में से एक का उपयोग करना होगा )।

यदि anOptionalIntकोई मान होता है, तो इसे बिना किसी अपवाद के अनलॉक्ड किया जाएगा और नए numberस्थिरांक को सौंपा जाएगा । गार्ड के बाद कोड तब निष्पादित करना जारी रखेगा। यदि इसमें कोई मान नहीं है - गार्ड कोष्ठक के भीतर कोड को निष्पादित करेगा, जिससे नियंत्रण स्थानांतरित हो जाएगा, ताकि उसके तुरंत बाद कोड निष्पादित नहीं होगा।

गार्ड स्टेटमेंट के बारे में असली साफ बात यह है कि अब कोड में उपयोग करने के लिए अलिखित मान उपलब्ध है जो कथन का अनुसरण करता है (जैसा कि हम जानते हैं कि भविष्य का कोड केवल तभी निष्पादित हो सकता है जब वैकल्पिक का मान हो)। बयानों के अनुसार, कई घोंसले के शिकार द्वारा बनाए गए 'कयामत के पिरामिड' को खत्म करने के लिए यह बहुत अच्छा है ।

उदाहरण के लिए:

guard let number = anOptionalInt else {
    return
}

print("anOptionalInt contains a value, and it’s: \(number)!")

गार्ड भी उन्हीं साफ-सुथरी चालों का समर्थन करते हैं जो यदि कथन का समर्थन करती हैं, जैसे एक ही समय में कई वैकल्पिकों को खोलना और whereक्लॉज का उपयोग करना ।

चाहे आप एक या गार्ड स्टेटमेंट का पूरी तरह से उपयोग करते हैं, इस बात पर निर्भर करता है कि भविष्य में किसी कोड को एक मान शामिल करने के लिए वैकल्पिक की आवश्यकता है या नहीं ।

निल कॉलेशिंग ऑपरेटर

शून्य वालों ऑपरेटर के एक गंधा आशुलिपि संस्करण है त्रिगुट सशर्त ऑपरेटर , मुख्य रूप से गैर optionals को optionals कन्वर्ट करने के लिए बनाया गया है। इसका सिंटैक्स है a ?? b, जहां aएक वैकल्पिक प्रकार है और bयह उसी प्रकार है a(हालांकि आमतौर पर गैर-वैकल्पिक)।

यह अनिवार्य रूप से आपको कहने देता है “यदि aइसमें कोई मूल्य है, तो इसे रद्द करें। अगर इसके बाद वापस नहीं जाता है तो b"। उदाहरण के लिए, आप इसे इस तरह उपयोग कर सकते हैं:

let number = anOptionalInt ?? 0

यह एक numberनिरंतर Intप्रकार को परिभाषित करेगा , जिसमें या तो मान शामिल होगा anOptionalInt, यदि इसमें कोई मान है, या 0अन्यथा।

इसके लिए बस शॉर्टहैंड है:

let number = anOptionalInt != nil ? anOptionalInt! : 0

वैकल्पिक चेनिंग

आप वैकल्पिक कॉलिंग का उपयोग कर सकते हैं ताकि किसी विधि पर कॉल किया जा सके या वैकल्पिक पर किसी संपत्ति का उपयोग किया जा सके। यह बस इसका ?उपयोग करते समय चर नाम के साथ प्रत्यय लगाकर किया जाता है।

उदाहरण के लिए, मान लें कि हमारे पास एक चर है foo, एक वैकल्पिक Fooउदाहरण।

var foo : Foo?

अगर हम fooउस तरीके को कॉल करना चाहते हैं जो कुछ भी वापस नहीं करता है, तो हम बस कर सकते हैं:

foo?.doSomethingInteresting()

यदि fooकोई मान है, तो इस पद्धति को उस पर कॉल किया जाएगा। यदि ऐसा नहीं होता है, तो कुछ भी बुरा नहीं होगा - कोड बस निष्पादित करना जारी रखेगा।

(यह nilउद्देश्य-सी में संदेश भेजने के लिए समान व्यवहार है)

इसलिए इसका उपयोग गुणों को सेट करने के साथ-साथ कॉल विधियों के लिए भी किया जा सकता है। उदाहरण के लिए:

foo?.bar = Bar()

फिर, यहाँ कुछ भी बुरा नहीं होगा अगर fooहै nil। आपका कोड बस क्रियान्वित होता रहेगा।

एक और साफ-सुथरी ट्रिक जो आपको वैकल्पिक चैनिंग करने देती है, यह जाँचती है कि कोई प्रॉपर्टी सेट करना या कोई विधि कॉल करना सफल था। आप रिटर्न मान की तुलना करके ऐसा कर सकते हैं nil

(ऐसा इसलिए है क्योंकि एक वैकल्पिक मूल्य एक विधि के Void?बजाय वापस आ जाएगा Voidजो कुछ भी वापस नहीं करता है)

उदाहरण के लिए:

if (foo?.bar = Bar()) != nil {
    print("bar was set successfully")
} else {
    print("bar wasn’t set successfully")
}

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

इसके अलावा, जैसा कि नाम से पता चलता है, आप इन कथनों को एक साथ 'चेन' कर सकते हैं। इसका मतलब है कि अगर fooकोई वैकल्पिक संपत्ति है baz, जिसमें एक संपत्ति है qux- आप निम्नलिखित लिख सकते हैं:

let optionalQux = foo?.baz?.qux

फिर से, क्योंकि fooऔर bazवैकल्पिक हैं, से लौटाया गया मूल्य quxहमेशा एक वैकल्पिक होगा चाहे वह quxखुद वैकल्पिक हो।

map तथा flatMap

वैकल्पिक के साथ अक्सर उपयोग की जाने वाली सुविधा कार्य mapऔर flatMapकार्यों का उपयोग करने की क्षमता है । ये आपको वैकल्पिक वैरिएबल में गैर-वैकल्पिक परिवर्तन लागू करने की अनुमति देते हैं। यदि किसी वैकल्पिक का मान है, तो आप इसमें दिए गए परिवर्तन को लागू कर सकते हैं। यदि इसका कोई मूल्य नहीं है, तो यह बना रहेगा nil

उदाहरण के लिए, मान लें कि आपके पास एक वैकल्पिक स्ट्रिंग है:

let anOptionalString:String?

mapफ़ंक्शन को उस पर लागू करने से - हम stringByAppendingStringफ़ंक्शन का उपयोग करके इसे किसी अन्य स्ट्रिंग तक पहुंचाने के लिए कर सकते हैं ।

क्योंकि stringByAppendingStringएक गैर-वैकल्पिक स्ट्रिंग तर्क लेता है, हम अपने वैकल्पिक स्ट्रिंग को सीधे इनपुट नहीं कर सकते। हालाँकि, उपयोग करके map, हम अनुमति दे सकते हैं कि stringByAppendingStringयदि anOptionalStringकोई मान है तो इसका उपयोग किया जा सकता है ।

उदाहरण के लिए:

var anOptionalString:String? = "bar"

anOptionalString = anOptionalString.map {unwrappedString in
    return "foo".stringByAppendingString(unwrappedString)
}

print(anOptionalString) // Optional("foobar")

हालाँकि, यदि anOptionalStringकोई मान नहीं है , तो mapवापस आ जाएगा nil। उदाहरण के लिए:

var anOptionalString:String?

anOptionalString = anOptionalString.map {unwrappedString in
    return "foo".stringByAppendingString(unwrappedString)
}

print(anOptionalString) // nil

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

try!

स्विफ्ट के एरर हैंडलिंग सिस्टम को सुरक्षित रूप से Do-Try-Catch के साथ प्रयोग किया जा सकता है :

do {
    let result = try someThrowingFunc() 
} catch {
    print(error)
}

यदि someThrowingFunc()कोई त्रुटि करता है, तो त्रुटि को catchब्लॉक में सुरक्षित रूप से पकड़ा जाएगा ।

errorलगातार आप में देख catchब्लॉक हमारे द्वारा घोषित नहीं किया गया है - यह स्वचालित रूप से द्वारा उत्पन्न कर रहा है catch

आप खुद को घोषित कर सकते हैं error, इसका फायदा यह है कि इसे एक उपयोगी प्रारूप में डालने में सक्षम है, उदाहरण के लिए:

do {
    let result = try someThrowingFunc()    
} catch let error as NSError {
    print(error.debugDescription)
}

tryइस तरह का उपयोग करना फेंकने के कार्यों से आने वाली त्रुटियों को आज़माने, पकड़ने और संभालने का उचित तरीका है।

वहाँ भी है try?जो त्रुटि को अवशोषित करता है:

if let result = try? someThrowingFunc() {
    // cool
} else {
    // handle the failure, but there's no error information available
}

लेकिन स्विफ्ट की त्रुटि से निपटने की प्रणाली भी इसके साथ "बल प्रयास" करने का एक तरीका प्रदान करती है try!:

let result = try! someThrowingFunc()

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

आपको केवल कभी-कभी उपयोग करना चाहिए try!यदि आप यह साबित कर सकते हैं कि इसका परिणाम आपके संदर्भ में कभी भी विफल नहीं होगा - और यह बहुत दुर्लभ है।

अधिकांश समय आप पूर्ण Do-Try-Catch प्रणाली का उपयोग करेंगे - और वैकल्पिक एक, try?दुर्लभ मामलों में जहां त्रुटि को संभालना महत्वपूर्ण नहीं है।


साधन


87
व्यक्तिगत रूप से, मैं यह सब लिखने के प्रयास में लगाने के लिए धन्यवाद देना चाहूंगा। मुझे लगता है कि यह निश्चित रूप से शुरुआती और विशेषज्ञों के लिए मददगार होगा।
प्रणव वाधवा

15
मुझे खुशी है कि आपने इसे मददगार पाया। यह उत्तर सामुदायिक विकि है, इसलिए यह कई लोगों (7, अब तक) के बीच एक सहयोग है!
jtbandes

1
यह त्रुटि मेरे मामले में रुक-रुक कर है। कोई सुझाव? में कोड stackoverflow.com/questions/50933681/...
py_ios_dev

1
शायद इसका जवाब अपडेट करने का समय है compactMap()बजाय इसके उपयोग करने के लिए flatMap()
निकोलस मारी

तो मुझे लगता है कि सबसे अच्छा और छोटा समाधान "निल कॉलेस्सिंग ऑपरेटर" है, है ना?
mehdigriche

65

टीएल; डीआर जवाब

साथ बहुत कुछ अपवादों को छोड़कर , इस नियम सुनहरा है:

के उपयोग से बचें !

वैरिएबल वैरिएबल वैकल्पिक ( ?), अव्यवस्थित रूप से अलिखित वैकल्पिक (IUO) ( !) नहीं

दूसरे शब्दों में, बल्कि उपयोग करें:
var nameOfDaughter: String?

के बजाय:
var nameOfDaughter: String!

वैकल्पिक चर का उपयोग कर if letया खोलनाguard let

या तो इस तरह के चर को खोलना:

if let nameOfDaughter = nameOfDaughter {
    print("My daughters name is: \(nameOfDaughter)")
}

या इस तरह:

guard let nameOfDaughter = nameOfDaughter else { return }
print("My daughters name is: \(nameOfDaughter)")

इस उत्तर को संक्षिप्त रूप में पढ़ा गया था, पूर्ण समझ के लिए स्वीकृत उत्तर पढ़ें


साधन


40

यह सवाल SO पर सभी समय आता है । यह पहली चीजों में से एक है जो नए स्विफ्ट डेवलपर्स के साथ संघर्ष करते हैं।

पृष्ठभूमि:

स्विफ्ट उन मूल्यों से निपटने के लिए "वैकल्पिक" की अवधारणा का उपयोग करता है जिनमें मूल्य शामिल हो सकते हैं, या नहीं। C जैसी अन्य भाषाओं में, आप यह दर्शाने के लिए एक चर में 0 का मान संग्रहीत कर सकते हैं कि इसमें कोई मान नहीं है। हालांकि, क्या होगा यदि 0 एक वैध मूल्य है? तब आप -1 का उपयोग कर सकते हैं। क्या होगा अगर -1 एक वैध मूल्य है? और इसी तरह।

स्विफ्ट ऑप्शंस आपको किसी भी प्रकार का एक वैरिएबल सेट करने देता है जिसमें या तो वैल्यू वैल्यू होती है या कोई वैल्यू नहीं होती है।

जब आप किसी चर को माध्य (प्रकार x, या कोई मान नहीं) घोषित करते हैं, तो आप उस प्रकार के बाद एक प्रश्न चिह्न लगाते हैं।

एक वैकल्पिक वास्तव में एक कंटेनर होता है जिसमें या तो दिए गए प्रकार का एक चर होता है, या कुछ भी नहीं होता है।

अंदर एक मूल्य लाने के लिए एक वैकल्पिक "अलिखित" होने की आवश्यकता है।

"!" ऑपरेटर एक "फोर्स अनप्रैप" ऑपरेटर है। यह कहता है "मुझ पर भरोसा करो। मुझे पता है कि मैं क्या कर रहा हूं। मैं गारंटी देता हूं कि जब यह कोड चलेगा, तो चर में शून्य नहीं होगा।" यदि आप गलत हैं, तो आप दुर्घटनाग्रस्त हो जाते हैं।

जब तक आप वास्तव में नहीं जानते कि आप क्या कर रहे हैं, "से बचें!" बल पूर्ववत संचालक। स्विफ्ट प्रोग्रामर्स की शुरुआत के लिए यह दुर्घटनाओं का सबसे बड़ा स्रोत है।

वैकल्पिक से कैसे निपटें:

वैकल्पिक से निपटने के कई अन्य तरीके हैं जो सुरक्षित हैं। यहाँ कुछ हैं (एक विस्तृत सूची नहीं)

आप "वैकल्पिक बाइंडिंग" या "यदि" कहने दें "का उपयोग कर सकते हैं यदि इस वैकल्पिक में कोई मान है, तो उस मान को एक नए, गैर-वैकल्पिक चर में सहेजें। यदि वैकल्पिक में कोई मान नहीं है, तो कथन के आधार पर इसे छोड़ें। "।

यहाँ हमारे fooवैकल्पिक के साथ वैकल्पिक बंधन का एक उदाहरण है :

if let newFoo = foo //If let is called optional binding. {
  print("foo is not nil")
} else {
  print("foo is nil")
}

ध्यान दें कि जब आप वैकल्पिक बाइंडिंग का उपयोग करते हैं तो जो चर परिभाषित करते हैं, यदि मौजूद है (तो केवल "स्कोप में है") यदि यह कथन है।

वैकल्पिक रूप से, आप एक गार्ड स्टेटमेंट का उपयोग कर सकते हैं, जो चर के शून्य होने पर आपको अपने फ़ंक्शन से बाहर निकलने देता है:

func aFunc(foo: Int?) {
  guard let newFoo = input else { return }
  //For the rest of the function newFoo is a non-optional var
}

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

एक निर्माण भी है जिसे "नील कोलेसिंग ऑपरेटर" कहा जाता है। यह "वैकल्पिक_वर ?? रिप्लेसमेंट_वल" का रूप लेता है। यह गैर-वैकल्पिक वैरिएबल को उसी प्रकार के साथ लौटाता है जैसे वैकल्पिक में निहित डेटा। यदि वैकल्पिक में शून्य है, तो यह "??" के बाद अभिव्यक्ति का मान लौटाता है। प्रतीक।

तो आप इस तरह कोड का उपयोग कर सकते हैं:

let newFoo = foo ?? "nil" // "??" is the nil coalescing operator
print("foo = \(newFoo)")

आप कोशिश / कैच या गार्ड एरर हैंडलिंग का भी उपयोग कर सकते हैं, लेकिन आमतौर पर ऊपर दी गई अन्य तकनीकों में से एक क्लीनर है।

संपादित करें:

एक और, वैकल्पिक के साथ थोड़ा और सूक्ष्म गोत्र "अनुमानित रूप से अलिखित वैकल्पिक है। जब हम फू की घोषणा करते हैं, तो हम कर सकते हैं:

var foo: String!

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

तो यह कोड:

var foo: String!


let upperFoo = foo.capitalizedString

फू की पूंजीकृत संपत्ति के संदर्भ में दुर्घटनाग्रस्त हो जाएगा, भले ही हम जोर-जबरदस्ती फू न हों। प्रिंट ठीक लग रहा है, लेकिन यह नहीं है।

इस प्रकार आप वास्तव में अंतर्निहित अलिखित वैकल्पिक के साथ सावधान रहना चाहते हैं। (और शायद यहां तक ​​कि उन्हें पूरी तरह से बचें जब तक कि आपके पास वैकल्पिक की ठोस समझ न हो।)

नीचे पंक्ति: जब आप पहली बार स्विफ्ट सीख रहे हैं, तो "दिखाओ!" चरित्र भाषा का हिस्सा नहीं है। यह आपको परेशानी में डालने की संभावना है।


7
आपको इसे सार्वजनिक विकि बनाने पर विचार करना चाहिए।
वकामा

3
अपना उत्तर संपादित करें, और दाईं ओर संपादन बॉक्स के नीचे एक समुदाय विकि चेकबॉक्स है। अब आपको उत्तर के लिए प्रतिनिधि नहीं मिलेगा, लेकिन मुझे पता है कि यह वैसे भी एक निराशाजनक प्रतिनिधि नहीं है।
वकमा

6
यह देखते हुए कि यह सवाल साइट पर एक लाख बार पूछा जाता है, अगर मैं प्रश्न के उत्तर के रूप में स्व-उत्तर वाले प्रश्न को पोस्ट करने के लिए समय लेने जा रहा था, मुझे उम्मीद है कि उत्तर इससे कहीं अधिक पूर्ण है। guardखंड के बारे में कुछ भी नहीं है । वहाँ के उपयोग के बारे में कुछ भी नहीं है if varजो सिर्फ एक निर्माण के रूप में मान्य है if letwhereजब हम if letबंधन के बारे में बात कर रहे हों, तो मुझे लगता है कि यह उल्लेख के लायक कुछ भी नहीं है (यह कई मामलों में नेस्टिंग की एक पूरी परत को हटा देता है)। वैकल्पिक चेनिंग के बारे में कुछ भी नहीं है।
22

6
और जब आप स्पष्ट रूप से अलिखित वैकल्पिक का उल्लेख करते हैं, तो आप यह भी उल्लेख नहीं करते हैं कि आप पूर्वोक्त वैकल्पिक ट्रिक्स का उपयोग सुरक्षित रूप से निहित अलिखित वैकल्पिक को अनचाहे करने के लिए कर सकते हैं। हम एक ही खंड में कई विकल्पों को उजागर नहीं करते हैं।
nhgrif

1
@ होग्रीफ, मैंने कहा था "आप ट्रायल / कैच या गार्ड एरर हैंडलिंग का भी उपयोग कर सकते हैं, लेकिन आम तौर पर ऊपर दी गई अन्य तकनीकों में से एक क्लीनर है।" आपके पास निश्चित रूप से कुछ अच्छे बिंदु हैं। यह एक काफी बड़ा विषय है। अपने स्वयं के उत्तर के योगदान के बारे में कैसे उन बातों को शामिल करता है जो मैंने टिप्पणी करने के बजाय नहीं किया था? इस तरह सवाल और यह जवाब साइट के लिए एक बेहतर संपत्ति बन जाते हैं।
डंकन सी

13

चूंकि उपरोक्त उत्तर स्पष्ट रूप से बताते हैं कि कैसे वैकल्पिक रूप से सुरक्षित रूप से खेलना है। मैं यह समझाने की कोशिश करूंगा कि वैकल्पिक क्या वास्तव में तेज हैं।

वैकल्पिक चर घोषित करने का दूसरा तरीका है

var i : Optional<Int>

और वैकल्पिक प्रकार दो मामलों के साथ एक गणना के अलावा कुछ भी नहीं है

 enum Optional<Wrapped> : ExpressibleByNilLiteral {
    case none 
    case some(Wrapped)
    .
    .
    .
}

इसलिए हमारे वेरिएबल 'i' को एक nil असाइन करना है। हम var i = Optional<Int>.none किसी मान को असाइन या असाइन कर सकते हैं , हम कुछ मान पास करेंगे var i = Optional<Int>.some(28)

स्विफ्ट के अनुसार, 'निल' मूल्य का अभाव है। और nilहमें इनिशियलाइज़ किए गए एक उदाहरण को बनाने के लिए हमें एक प्रोटोकॉल के अनुरूप होना चाहिए ExpressibleByNilLiteralऔर अगर आपको यह अनुमान लगाया जाता है कि केवल इसके Optionalsअनुरूप है ExpressibleByNilLiteralऔर अन्य प्रकारों के अनुरूप होना हतोत्साहित करता है।

ExpressibleByNilLiteralएक एकल विधि है, init(nilLiteral:)जो निल के साथ एक वृत्त को आरंभ करती है। आप आमतौर पर इस पद्धति को कॉल नहीं कर सकते हैं और स्विफ्ट डॉक्यूमेंटेशन के अनुसार इस इनिशियलाइज़र को सीधे कॉल करने के लिए हतोत्साहित किया जाता है क्योंकि कंपाइलर इसे तब कहता है जब आप एक वैकल्पिक प्रकार को nilशाब्दिक रूप से इनिशियलाइज़ करते हैं ।

यहां तक ​​कि अपने आप को वैकल्पिक के आसपास मेरे सिर को लपेटने का कोई इरादा नहीं है: डी हैप्पी स्विफ्टिंग ऑल


12

पहले, आपको पता होना चाहिए कि एक वैकल्पिक मूल्य क्या है। आप विस्तार के लिए स्विफ्ट प्रोग्रामिंग भाषा में कदम रख सकते हैं ।

दूसरा, आपको पता होना चाहिए कि वैकल्पिक मूल्य में दो स्थितियां हैं। एक पूर्ण मान है, और दूसरा शून्य मान है। इसलिए इससे पहले कि आप एक वैकल्पिक मूल्य लागू करें, आपको यह जांचना चाहिए कि यह किस राज्य का है।

आप if let ...या guard let ... elseतो और उपयोग कर सकते हैं ।

एक अन्य तरीका, यदि आप अपने कार्यान्वयन से पहले चर राज्य की जांच नहीं करना चाहते हैं, तो आप var buildingName = buildingName ?? "buildingName"इसके बजाय भी उपयोग कर सकते हैं ।


8

मुझे यह त्रुटि एक बार तब हुई जब मैं अपने आउटलेट मूल्यों को सेग विधि की तैयारी से निम्नानुसार सेट करने का प्रयास कर रहा था:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? DestinationVC{

        if let item = sender as? DataItem{
            // This line pops up the error
            destination.nameLabel.text = item.name
        }
    }
}

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

तो मैंने इसे इस तरह हल किया:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? DestinationVC{

        if let item = sender as? DataItem{
            // Created this method in the destination Controller to update its outlets after it's being initialized and loaded
            destination.updateView(itemData:  item)
        }
    }
}

गंतव्य नियंत्रक:

// This variable to hold the data received to update the Label text after the VIEW DID LOAD
var name = ""

// Outlets
@IBOutlet weak var nameLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    nameLabel.text = name
}

func updateView(itemDate: ObjectModel) {
    name = itemDate.name
}

मुझे उम्मीद है कि यह उत्तर किसी को भी इस मुद्दे के साथ मदद करता है क्योंकि मैंने पाया कि उत्तर मिला वैकल्पिक की समझ के लिए महान संसाधन है और वे कैसे काम करते हैं लेकिन इस मुद्दे को सीधे संबोधित नहीं किया है।


बस updateViewगंतव्य कंट्रोलर में कॉल करने के लिए उल्लेख करना न भूलें ;)
अहमद एफ

@ अहमद अच्छी बात है। फिर भी बुला updateViewगंतव्य नियंत्रक में इस मामले में की जरूरत नहीं है के रूप में मैं उपयोग कर रहा हूँ nameस्थापित करने के लिए चर nameLabel.textमें viewDidLoad। लेकिन अगर हम बहुत सारे सेटअप कर रहे थे, तो निश्चित रूप से ऐसा करने से एक और कार्य करना बेहतर होगा और viewDidLoadइसके बजाय इसे कॉल करना होगा।
विस्सा

7

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

इस तरह की घातक त्रुटि के लिए कई परिदृश्य हैं:

  1. जबरन खोले गए:

    let user = someVariable!

    यदि someVariableशून्य है, तो आपको दुर्घटना होगी। जब आप मूल रूप से संकलक से जिम्मेदारी की जांच करवाते हैं, तो मूल रूप से मजबूर करने वाले अनिच्छुक काम करने से आप अनिच्छुक हो जाते हैं। और लगता है कि क्या होता है अगर किसी तरह एक शून्य मूल्य में समाप्त होता है someVariable?

    समाधान? वैकल्पिक बाइंडिंग (उर्फ इफ़-लेट) का उपयोग करें, वहाँ चर प्रसंस्करण करें:

    if user = someVariable {
        // do your stuff
    }
  2. मजबूर (नीचे) जातियां:

    let myRectangle = someShape as! Rectangle

    यहाँ बल द्वारा कास्टिंग आप संकलक को अब चिंता करने के लिए नहीं कहते हैं, क्योंकि आपके पास हमेशा एक Rectangleउदाहरण होगा। और जब तक वह धारण करता है, आपको चिंता करने की आवश्यकता नहीं है। समस्या तब शुरू होती है जब आप या आपके सहकर्मी परियोजना से गैर-आयत मानों को प्रसारित करना शुरू करते हैं।

    समाधान? वैकल्पिक बाइंडिंग (उर्फ इफ़-लेट) का उपयोग करें, वहाँ चर प्रसंस्करण करें:

    if let myRectangle = someShape as? Rectangle {
        // yay, I have a rectangle
    }
  3. वैकल्पिक रूप से अपरिवर्तित वैकल्पिक। मान लेते हैं कि आपके पास निम्न वर्ग की परिभाषा है:

    class User {
        var name: String!
    
        init() {
            name = "(unnamed)"
        }
    
        func nicerName() {
            return "Mr/Ms " + name
        }
    }

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

    समाधान? उनका उपयोग न करें :) जब तक आप 102% सुनिश्चित नहीं हो जाते हैं कि संपत्ति को हमेशा गैर-शून्य मान होगा, तब तक इसका उपयोग करने की आवश्यकता होती है। ज्यादातर मामलों में वैकल्पिक या गैर-वैकल्पिक में परिवर्तित करने से काम चल जाएगा। इसे गैर-वैकल्पिक बनाने से कंपाइलर को उस संपत्ति के लिए एक मूल्य देने में चूक गए कोड रास्तों को बताने में मदद मिलेगी

  4. असंबद्ध, या अभी तक जुड़ा नहीं है, आउटलेट। यह परिदृश्य # 3 का एक विशेष मामला है। मूल रूप से आपके पास कुछ XIB- लोडेड वर्ग है जिसका आप उपयोग करना चाहते हैं।

    class SignInViewController: UIViewController {
    
        @IBOutlet var emailTextField: UITextField!
    }

    अब अगर आप XIB एडिटर से आउटलेट कनेक्ट करने से चूक गए हैं, तो जैसे ही आप आउटलेट का उपयोग करना चाहेंगे, ऐप क्रैश हो जाएगा। समाधान? सुनिश्चित करें कि सभी आउटलेट जुड़े हुए हैं। या ?उन पर ऑपरेटर का उपयोग करें emailTextField?.text = "my@email.com":। या आउटलेट को वैकल्पिक के रूप में घोषित करें, हालांकि इस मामले में कंपाइलर आपको कोड पर इसे अनचेक करने के लिए मजबूर करेगा।

  5. उद्देश्य-सी से आने वाले मान, और इसमें अशक्तता की व्याख्या नहीं है। मान लेते हैं कि हमारे पास निम्न उद्देश्य-सी श्रेणी है:

    @interface MyUser: NSObject
    @property NSString *name;
    @end

    अब यदि कोई अशक्तता एनोटेशन निर्दिष्ट नहीं है (या तो स्पष्ट रूप से या NS_ASSUME_NONNULL_BEGIN/ के माध्यम से NS_ASSUME_NONNULL_END), तो nameसंपत्ति स्विफ्ट में आयात की जाएगी String!(एक आईयूओ - अंतर्निहित अलिखित वैकल्पिक)। जैसे ही कुछ स्विफ्ट कोड मूल्य का उपयोग करना चाहेगा, यह nameशून्य होने पर दुर्घटनाग्रस्त हो जाएगा ।

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


2

यह एक महत्वपूर्ण टिप्पणी है और इसलिए कि जब यह डिबगिंग nilमूल्यों की बात आती है तो अंतर्निहित अलिखित वैकल्पिक क्यों भ्रामक हो सकता है ।

निम्नलिखित कोड के बारे में सोचें: यह बिना किसी त्रुटि / चेतावनी के संकलित करता है:

c1.address.city = c3.address.city

फिर भी रनटाइम के दौरान यह निम्नलिखित त्रुटि देता है: घातक त्रुटि: एक वैकल्पिक मान को हटाते समय अप्रत्याशित रूप से शून्य पाया गया

क्या आप बता सकते हैं कि कौन सी वस्तु है nil?

आप नहीं कर सकते!

पूर्ण कोड होगा:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var c1 = NormalContact()
        let c3 = BadContact()

        c1.address.city = c3.address.city // compiler hides the truth from you and then you sudden get a crash
    }
}

struct NormalContact {
    var address : Address = Address(city: "defaultCity")
}

struct BadContact {
    var address : Address!
}

struct Address {
    var city : String
}

लंबी कहानी का उपयोग करके var address : Address!आप इस संभावना को छिपा रहे हैं कि एक चर nilअन्य पाठकों से हो सकता है। और जब यह दुर्घटनाग्रस्त हो जाता है तो आप "क्या नरक है? मेरा addressकोई वैकल्पिक नहीं है, तो मैं दुर्घटनाग्रस्त क्यों हूं?"

इसलिए इस तरह लिखना बेहतर है:

c1.address.city = c2.address!.city  // ERROR:  Fatal error: Unexpectedly found nil while unwrapping an Optional value 

क्या अब आप मुझे बता सकते हैं कि वह कौन सी वस्तु थी nil?

इस बार आपको कोड अधिक स्पष्ट कर दिया गया है। आप तर्कसंगत रूप से सोच सकते हैं और सोच सकते हैं कि यह वह addressपैरामीटर है जो जबरदस्ती अलिखित था।

पूर्ण कोड होगा:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var c1 = NormalContact()
        let c2 = GoodContact()

        c1.address.city = c2.address!.city
        c1.address.city = c2.address?.city // not compile-able. No deceiving by the compiler
        c1.address.city = c2.address.city // not compile-able. No deceiving by the compiler
        if let city = c2.address?.city {  // safest approach. But that's not what I'm talking about here. 
            c1.address.city = city
        }

    }
}

struct NormalContact {
    var address : Address = Address(city: "defaultCity")
}

struct GoodContact {
    var address : Address?
}

struct Address {
    var city : String
}

2

त्रुटियों EXC_BAD_INSTRUCTIONऔर fatal error: unexpectedly found nil while implicitly unwrapping an Optional valueप्रकट होता है जब आप एक घोषित किया है @IBOutlet, लेकिन स्टोरीबोर्ड से जुड़ा नहीं है ।

आपको यह भी सीखना चाहिए कि कैसे वैकल्पिक काम करते हैं, अन्य उत्तरों में उल्लेख किया गया है, लेकिन यह एकमात्र समय है जो ज्यादातर मुझे दिखाई देता है।


क्या @IBOutletइस त्रुटि का कारण घातक त्रुटि नहीं होनी चाहिए : त्रुटि के वैकल्पिक मान संस्करण को निहित करते समय अप्रत्याशित रूप से पाया गया शून्य ?
21

1
यह सच है। हो सकता है कि जब मैं जवाब भेजता हूं कि मेरा क्या मतलब है, और मैंने पहले घातक त्रुटि संदेश को कॉपी किया। हामिश का जवाब इस बारे में बहुत पूरा लगता है।
अली मोहम्मद

2

यदि आपको यह त्रुटि मिली है तो कलेक्शन व्यू में CustomCell फ़ाइल और कस्टम xib भी बनाने का प्रयास करें।

मुख्य कोड पर ViewDidLoad () में यह कोड जोड़ें।

    let nib = UINib(nibName: "CustomnibName", bundle: nil)
    self.collectionView.register(nib, forCellWithReuseIdentifier: "cell")

0

एक टेबल व्यू कंट्रोलर से एक व्यू कंट्रोलर से एक बहस करते समय मुझे यह त्रुटि आई क्योंकि मैं मुख्य स्टोरीबोर्ड में व्यू कंट्रोलर के लिए कस्टम क्लास का नाम बताना भूल गया था।

कुछ आसान है जो जाँचने योग्य है अगर बाकी सब ठीक लगे

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