स्विफ्ट में एक वैकल्पिक मूल्य क्या है?


267

से एप्पल के प्रलेखन :

आप उन मूल्यों के साथ काम करने के लिए उपयोग ifऔर letएक साथ कर सकते हैं जो गायब हो सकते हैं। इन मूल्यों को वैकल्पिक के रूप में दर्शाया गया है। एक वैकल्पिक मूल्य में या तो एक मान होता है या इसमें nilयह इंगित करने के लिए होता है कि मान गायब है। ?मूल्य को वैकल्पिक के रूप में चिह्नित करने के लिए एक प्रश्न चिह्न ( ) लिखें ।

आप वैकल्पिक मूल्य का उपयोग क्यों करना चाहेंगे?



1
वैकल्पिक को विकल्प / शायद मोनड के कार्यान्वयन के रूप में भी देखा जा सकता हैयहाँ यह ब्लॉग यह समझाने की कोशिश करने का एक अच्छा काम करता है कि अन्यथा एक कठिन अवधारणा क्या है।
स्टुअर्टएलसी

tldr: "स्विफ्ट के बारे में आपको स्पष्ट होना चाहिए कि मूल्य कब गायब हो सकता है और कब अस्तित्व की गारंटी देता है।" नीवन राजा के शानदार जवाब के नीचे से
जोंतन

जवाबों:


531

स्विफ्ट में एक वैकल्पिक एक प्रकार है जो या तो मूल्य या कोई मूल्य नहीं पकड़ सकता है। वैकल्पिक ?को किसी भी प्रकार से जोड़कर लिखा जाता है :

var name: String? = "Bertie"

वैकल्पिक (जेनरिक के साथ) समझने के लिए सबसे कठिन स्विफ्ट अवधारणाओं में से एक है। क्योंकि वे कैसे लिखे और उपयोग किए जाते हैं, इस बात का गलत अंदाजा लगाना आसान है कि वे क्या हैं। सामान्य स्ट्रिंग बनाने के लिए ऊपर दिए गए वैकल्पिक की तुलना करें:

var name: String = "Bertie" // No "?" after String

वाक्य रचना से ऐसा लगता है कि वैकल्पिक स्ट्रिंग एक साधारण स्ट्रिंग के समान है। यह। एक वैकल्पिक स्ट्रिंग कुछ "वैकल्पिक" सेटिंग के साथ स्ट्रिंग नहीं है। यह स्ट्रिंग की एक विशेष किस्म नहीं है। एक स्ट्रिंग और एक वैकल्पिक स्ट्रिंग पूरी तरह से अलग प्रकार के होते हैं।

यहां यह जानना सबसे महत्वपूर्ण है: एक वैकल्पिक एक प्रकार का कंटेनर है। एक वैकल्पिक स्ट्रिंग एक कंटेनर है जिसमें एक स्ट्रिंग हो सकता है। एक वैकल्पिक Int एक कंटेनर है जिसमें एक Int हो सकता है। एक प्रकार के पार्सल के रूप में एक वैकल्पिक के बारे में सोचो। इससे पहले कि आप इसे खोलें (या वैकल्पिक की भाषा में "अनचाहे") आपको पता नहीं चलेगा कि इसमें कुछ है या कुछ नहीं है।

आप देख सकते हैं कि स्विफ्ट स्टैंडर्ड लाइब्रेरी में "वैकल्पिक" को किसी भी स्विफ्ट फ़ाइल में टाइप करके और उस पर it-क्लिक करके वैकल्पिक कैसे लागू किया जाता है। यहाँ परिभाषा का महत्वपूर्ण हिस्सा है:

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

वैकल्पिक सिर्फ एक है enumजो दो मामलों में से एक हो सकता है: .noneया .some। यदि यह है .some, तो एक संबद्ध मूल्य है, जो ऊपर दिए गए उदाहरण में, String"हैलो" होगा। एक वैकल्पिक संबंधित मूल्य को एक प्रकार देने के लिए जेनरिक का उपयोग करता है। वैकल्पिक स्ट्रिंग का प्रकार Stringयह नहीं है Optional, या अधिक सटीक है Optional<String>

सब कुछ स्विफ्ट वैकल्पिक के साथ करता है पढ़ने और लिखने के कोड को अधिक धाराप्रवाह बनाने के लिए जादू है। दुर्भाग्य से यह वास्तव में काम करने के तरीके को अस्पष्ट करता है। मैं बाद में कुछ ट्रिक्स से गुजरूंगा।

नोट: मैं वैकल्पिक चर के बारे में बात कर रहा हूँ, लेकिन वैकल्पिक स्थिरांक बनाना भी ठीक है। मैं सभी प्रकारों को उनके प्रकार के साथ चिह्नित करता हूं ताकि प्रकार के प्रकारों को समझने में आसानी हो, लेकिन आपको अपने कोड में नहीं होना चाहिए।


कैसे वैकल्पिक बनाने के लिए

एक वैकल्पिक बनाने के लिए, ?उस प्रकार के बाद जोड़ें जिसे आप लपेटना चाहते हैं। कोई भी प्रकार वैकल्पिक हो सकता है, यहां तक ​​कि आपके स्वयं के कस्टम प्रकार भी। आपके पास प्रकार और के बीच का स्थान नहीं हो सकता ?

var name: String? = "Bob" // Create an optional String that contains "Bob"
var peter: Person? = Person() // An optional "Person" (custom type)

// A class with a String and an optional String property
class Car {
var modelName: String // must exist
var internalName: String? // may or may not exist
}

वैकल्पिक का उपयोग करना

आप nilयह देखने के लिए वैकल्पिक की तुलना कर सकते हैं कि क्या इसका मूल्य है:

var name: String? = "Bob"
name = nil // Set name to nil, the absence of a value
if name != nil {
    print("There is a name")
}
if name == nil { // Could also use an "else"
    print("Name has no value")
}

यह थोड़ा भ्रमित करने वाला है। इसका तात्पर्य है कि एक वैकल्पिक या तो एक चीज है या कोई अन्य। यह या तो शून्य है या यह "बॉब" है। यह सच नहीं है, वैकल्पिक कुछ और में परिवर्तित नहीं होता है। इसे शून्य से तुलना करना आसान कोड को पढ़ने के लिए एक चाल है। यदि कोई वैकल्पिक शून्य के बराबर होता है, तो इसका अर्थ है कि वर्तमान में एनम सेट है .none


केवल वैकल्पिक शून्य हो सकते हैं

यदि आप गैर-वैकल्पिक चर को शून्य पर सेट करने का प्रयास करते हैं, तो आपको एक त्रुटि मिलेगी।

var red: String = "Red"
red = nil // error: nil cannot be assigned to type 'String'

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

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


एक वैकल्पिक का उपयोग करने के लिए, आप इसे "अनफ्रैप" करते हैं

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

var name: String? = "Bob"
let unwrappedName: String = name!
print("Unwrapped name: \(unwrappedName)")

name = nil
let nilName: String = name! // Runtime crash. Unexpected nil.

वैकल्पिक की जाँच करना और उसका उपयोग करना

चूँकि आपको हमेशा अल्टरनेपिंग और एक वैकल्पिक उपयोग करने से पहले नील की जांच करनी चाहिए, यह एक सामान्य पैटर्न है:

var mealPreference: String? = "Vegetarian"
if mealPreference != nil {
    let unwrappedMealPreference: String = mealPreference!
    print("Meal: \(unwrappedMealPreference)") // or do something useful
}

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

var mealPreference: String? = "Vegetarian"
if let unwrappedMealPreference: String = mealPreference {
    print("Meal: \(unwrappedMealPreference)") 
}

यह एक अस्थायी स्थिरांक (या यदि आप के letसाथ परिवर्तनशील var) बनाता है जिसका दायरा केवल if के ब्रेसिज़ के भीतर है। चूँकि "undrappedMealPreference" या "realMealPreference" जैसे नाम का उपयोग करना एक बोझ है, इसलिए स्विफ्ट आपको मूल चर नाम का पुन: उपयोग करने की अनुमति देता है, जिससे ब्रैकेट स्कोप के भीतर एक अस्थायी बना होता है

var mealPreference: String? = "Vegetarian"
if let mealPreference: String = mealPreference {
    print("Meal: \(mealPreference)") // separate from the other mealPreference
}

यह प्रदर्शित करने के लिए कुछ कोड है कि एक अलग चर का उपयोग किया जाता है:

var mealPreference: String? = "Vegetarian"
if var mealPreference: String = mealPreference {
    print("Meal: \(mealPreference)") // mealPreference is a String, not a String?
    mealPreference = "Beef" // No effect on original
}
// This is the original mealPreference
print("Meal: \(mealPreference)") // Prints "Meal: Optional("Vegetarian")"

वैकल्पिक बाध्यकारी शून्य के बराबर है या नहीं यह देखने के लिए जाँच करके वैकल्पिक बाइंडिंग कार्य करता है। यदि ऐसा नहीं होता है, तो यह प्रदान की गई स्थिरांक में वैकल्पिक को खोल देता है और ब्लॉक को निष्पादित करता है। Xcode 8.3 और बाद में (स्विफ्ट 3.1), इस तरह से एक वैकल्पिक प्रिंट करने की कोशिश करना एक बेकार चेतावनी का कारण होगा। debugDescriptionइसे शांत करने के लिए वैकल्पिक का उपयोग करें :

print("\(mealPreference.debugDescription)")

इसके लिए वैकल्पिक क्या हैं?

वैकल्पिक उपयोग के दो मामले हैं:

  1. चीजें जो विफल हो सकती हैं (मुझे कुछ उम्मीद थी लेकिन मुझे कुछ नहीं मिला)
  2. चीजें जो अब कुछ भी नहीं हैं लेकिन बाद में कुछ हो सकती हैं (और इसके विपरीत)

कुछ ठोस उदाहरण:

  • एक संपत्ति जो वहाँ है या नहीं हो सकता है, की तरह middleNameया spouseएक में Personकक्षा
  • एक विधि जो एक मान या कुछ भी नहीं लौटा सकती है, जैसे कि एक सरणी में मैच की खोज करना
  • एक विधि जो या तो एक परिणाम दे सकती है या एक त्रुटि प्राप्त कर सकती है और कुछ भी नहीं लौटा सकती है, जैसे कि फ़ाइल की सामग्री को पढ़ने की कोशिश करना (जो आमतौर पर फ़ाइल के डेटा को लौटाता है) लेकिन फ़ाइल मौजूद नहीं है
  • प्रतिनिधि गुण, जिन्हें हमेशा सेट नहीं करना पड़ता है और आमतौर पर आरंभ के बाद सेट किया जाता है
  • के लिए weakकक्षाओं में गुण। जिस चीज को वे इंगित करते हैं, वह nilकिसी भी समय सेट किया जा सकता है
  • एक बड़ा संसाधन जिसे स्मृति को पुनः प्राप्त करने के लिए जारी करना पड़ सकता है
  • जब आपको यह जानने के लिए एक तरीका की आवश्यकता होती है कि कोई मान सेट किया गया है (डेटा अभी तक लोड नहीं किया गया है> डेटा) के बजाय एक अलग डेटाकोल्ड का उपयोग कर Boolean

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


की तुलना में nil

आप के रूप में किसी भी वैकल्पिक का उपयोग करने में सक्षम हो Boolean:

let leatherTrim: CarExtras? = nil
if leatherTrim {
    price = price + 1000
}

स्विफ्ट के अधिक हाल के संस्करणों में आपको उपयोग करना होगा leatherTrim != nil। ऐसा क्यों है? समस्या यह है कि एक Booleanवैकल्पिक में लपेटा जा सकता है। अगर आपको यह Booleanपसंद है:

var ambiguous: Boolean? = false

इसके दो प्रकार के "झूठे" हैं, एक जहां कोई मूल्य नहीं है और एक जहां इसका मूल्य है, लेकिन मूल्य है false। स्विफ्ट को अस्पष्टता से नफरत है इसलिए अब आपको हमेशा एक वैकल्पिक जांच करनी चाहिए nil

आप सोच सकते हैं कि एक वैकल्पिक बिंदु क्या Booleanहै? अन्य वैकल्पिकों की तरह .noneराज्य यह संकेत दे सकता है कि मूल्य अभी तक अज्ञात है। एक नेटवर्क कॉल के दूसरे छोर पर कुछ हो सकता है जो मतदान में कुछ समय लेता है। वैकल्पिक बूलियन को " थ्री-वैल्यू बूलियन " भी कहा जाता है


स्विफ्ट ट्रिक्स

वैकल्पिक काम करने के लिए स्विफ्ट कुछ तरकीबों का उपयोग करती है। साधारण दिखने वाले वैकल्पिक कोड की इन तीन पंक्तियों पर विचार करें;

var religiousAffiliation: String? = "Rastafarian"
religiousAffiliation = nil
if religiousAffiliation != nil { ... }

इन पंक्तियों में से कोई भी संकलन नहीं करना चाहिए।

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

मैं वैकल्पिक के कुछ कार्यान्वयन विवरणों के माध्यम से जाऊंगा जो इन पंक्तियों को काम करने की अनुमति देते हैं।


एक वैकल्पिक बनाना

?एक वैकल्पिक बनाने के लिए उपयोग कर रहा है वाक्य रचना चीनी, स्विफ्ट कंपाइलर द्वारा सक्षम है। यदि आप इसे लंबा करना चाहते हैं, तो आप इस तरह से एक वैकल्पिक बना सकते हैं:

var name: Optional<String> = Optional("Bob")

यह Optionalपहला इनिशियलाइज़र कहलाता है public init(_ some: Wrapped), जो कोष्ठक के भीतर उपयोग किए गए प्रकार से वैकल्पिक से जुड़े प्रकार को संक्रमित करता है।

वैकल्पिक बनाने और स्थापित करने का समान लंबा तरीका:

var serialNumber:String? = Optional.none
serialNumber = Optional.some("1234")
print("\(serialNumber.debugDescription)")

के लिए एक वैकल्पिक सेटिंग nil

आप बिना प्रारंभिक मूल्य के एक वैकल्पिक बना सकते हैं, या nilदोनों के प्रारंभिक मूल्य के साथ एक बना सकते हैं (दोनों का एक ही परिणाम है)।

var name: String?
var name: String? = nil

समान के लिए वैकल्पिक विकल्प को nilप्रोटोकॉल ExpressibleByNilLiteral(पहले नामित NilLiteralConvertible) द्वारा सक्षम किया गया है । वैकल्पिक को Optionalदूसरे इनिशियलाइज़र के साथ बनाया गया है public init(nilLiteral: ())। डॉक्स का कहना है कि आपको ExpressibleByNilLiteralवैकल्पिक के अलावा किसी भी चीज़ के लिए उपयोग नहीं करना चाहिए , क्योंकि इससे आपके कोड में नील का अर्थ बदल जाएगा, लेकिन ऐसा करना संभव है:

class Clint: ExpressibleByNilLiteral {
    var name: String?
    required init(nilLiteral: ()) {
        name = "The Man with No Name"
    }
}

let clint: Clint = nil // Would normally give an error
print("\(clint.name)")

एक ही प्रोटोकॉल आपको पहले से निर्मित वैकल्पिक को सेट करने की अनुमति देता है nil। हालांकि इसकी अनुशंसा नहीं की जाती है, आप सीधे nil शाब्दिक इनिलाइज़र का उपयोग कर सकते हैं:

var name: Optional<String> = Optional(nilLiteral: ())

के लिए एक वैकल्पिक तुलना nil

वैकल्पिक दो विशेष "==" और "! =" ऑपरेटर को परिभाषित करते हैं, जिसे आप Optionalपरिभाषा में देख सकते हैं । पहला ==आपको यह जांचने की अनुमति देता है कि क्या कोई वैकल्पिक शून्य के बराबर है। दो अलग-अलग वैकल्पिक जो कि .none पर सेट किए गए हैं, यदि संबंधित प्रकार समान हैं, तो हमेशा समान होंगे। जब आप शून्य से तुलना करते हैं, तो पर्दे के पीछे स्विफ्ट एक ही संबद्ध प्रकार का एक वैकल्पिक बनाता है, जो सेट किया जाता है। फिर उस तुलना के लिए उपयोग करता है।

// How Swift actually compares to nil
var tuxedoRequired: String? = nil
let temp: Optional<String> = Optional.none
if tuxedoRequired == temp { // equivalent to if tuxedoRequired == nil
    print("tuxedoRequired is nil")
}

दूसरा ==ऑपरेटर आपको दो वैकल्पिकों की तुलना करने की अनुमति देता है। दोनों को एक ही प्रकार का होना चाहिए और उस प्रकार के अनुरूप होना चाहिए Equatable(प्रोटोकॉल जो नियमित "==" ऑपरेटर) के साथ चीजों की तुलना करने की अनुमति देता है। स्विफ्ट (संभवतः) दो मूल्यों को उजागर करता है और सीधे उनकी तुलना करता है। यह उस मामले को भी संभालता है जहां एक या दोनों वैकल्पिक हैं .nonenilशाब्दिक की तुलना के बीच अंतर पर ध्यान दें ।

इसके अलावा, यह आपको किसी भी Equatableप्रकार के वैकल्पिक रैपिंग की तुलना करने की अनुमति देता है :

let numberToFind: Int = 23
let numberFromString: Int? = Int("23") // Optional(23)
if numberToFind == numberFromString {
    print("It's a match!") // Prints "It's a match!"
}

पर्दे के पीछे, स्विफ्ट तुलना के पहले गैर-वैकल्पिक को वैकल्पिक के रूप में लपेटता है। यह शाब्दिक के साथ भी काम करता है ( if 23 == numberFromString {)

मैंने कहा कि दो ==ऑपरेटर हैं, लेकिन वास्तव में एक तीसरा है जो आपको nilतुलना के बाईं ओर रखने की अनुमति देता है

if nil == name { ... }

नामकरण वैकल्पिक

गैर-वैकल्पिक प्रकारों से अलग प्रकार के वैकल्पिक नामकरण के लिए कोई स्विफ्ट सम्मेलन नहीं है। लोग यह दिखाने के लिए कुछ नाम जोड़ने से बचते हैं कि यह एक वैकल्पिक है (जैसे "alternMiddleName", या "possibleNumberAsString") और घोषणा को दिखाने दें कि यह एक वैकल्पिक प्रकार है। यह मुश्किल हो जाता है जब आप किसी वैकल्पिक से मूल्य को रखने के लिए कुछ नाम देना चाहते हैं। "मध्यनाम" नाम का अर्थ है कि यह एक स्ट्रिंग प्रकार है, इसलिए जब आप इसमें से स्ट्रिंग मान निकालते हैं, तो आप अक्सर "realMiddleName" या "unwrappedMiddleName" या "realMieldName" जैसे नामों के साथ समाप्त कर सकते हैं। वैकल्पिक बाइंडिंग का उपयोग करें और इसके चारों ओर प्राप्त करने के लिए चर नाम का पुन: उपयोग करें।


आधिकारिक परिभाषा

से "मूल बातें" में स्विफ्ट प्रोग्रामिंग भाषा :

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

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


खत्म करने के लिए, यहाँ वैकल्पिक के बारे में 1899 से एक कविता है:

कल सीढ़ी पर
मैं एक आदमी से मिला जो वहां नहीं था
वह आज फिर नहीं था
मैं चाहता हूं, काश वह
एंटीगोनिश चला जाता


और अधिक संसाधनों:


5
@KaDedeoglu दुर्भाग्य से स्टीव बहुत वैकल्पिक है। वह यहाँ था और अब वह नहीं है।
नीवन राजा

19
if myStringअब और संकलन नहीं है। आपको जरूरत है if myString != nilप्रलेखन देखें ।
पांग

5
के लिए सबसे अच्छा और स्पष्ट विवरण? तथा ! स्विफ्ट में उपयोग मैं वेब पर पाया। धन्यवाद
mindbomb

2
mateo गहराई में व्याख्या करता है, गहराई तक पहुँचने और आसान उदाहरण।
इलवतार_जीआर

4
इस स्पष्टीकरण के लिए धन्यवाद, यह Apple के स्वयं के प्रलेखन की तुलना में बहुत स्पष्ट है।
यतिहिसज्यो

16

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

var error: NSError? = nil

यह आपको डिफ़ॉल्ट मान भी देता है। यदि आप फ़ंक्शन कुछ भी पारित नहीं करते हैं, तो आप एक विधि को एक डिफ़ॉल्ट मान सेट कर सकते हैं

func doesntEnterNumber(x: Int? = 5) -> Bool {
    if (x == 5){
        return true
    } else {
        return false
    }
}

वाक्य "यदि यह शून्य है, तो इसके साथ किसी भी अभिव्यक्ति का परिणाम शून्य है" बस गलत है। वैकल्पिक मूल्य है जो अभिव्यक्ति में है, भले ही func isNil<T>(t: T?) -> Bool { return t == nil }वापस आ जाएगा । truenil
सच

अविश्वसनीय रूप से बुरा कोड नमूना। क्या आप कुछ बेहतर नहीं सोच सकते थे? बस क्यों नहीं return x == 5? 5 में ऐसा क्या खास है?
एटोमोस्क

नहीं, 2 साल पहले मैं कुछ बेहतर नहीं सोच सकता था। आज हाँ, लेकिन क्या इस बिंदु को पार किया जाता है? हाँ। इनपुट @Atomosk के लिए धन्यवाद, यह वास्तव में उपयोगी है।
जॉन रिसेल्वेटो

12

आपके पास एक चर नहीं हो सकता है जो nilस्विफ्ट में इंगित करता है - कोई संकेत नहीं है, और कोई अशक्त संकेत नहीं है। लेकिन एक एपीआई में, आप अक्सर एक विशिष्ट प्रकार के मूल्य, या मूल्य की कमी को इंगित करने में सक्षम होना चाहते हैं - जैसे मेरी खिड़की में एक प्रतिनिधि है, और यदि ऐसा है, तो यह कौन है? वैकल्पिक स्विफ्ट का प्रकार-सुरक्षित, मेमोरी-सुरक्षित तरीका है।


11

मैंने एक छोटा सा उत्तर दिया, जो ऊपर की सबसे अधिक रकम को एक शुरुआत के रूप में मेरे सिर में थी अनिश्चितता को साफ करने के लिए करता है:

ऑब्जेक्टिव-सी करने का विरोध किया, कोई चर शामिल कर सकते हैं नहीं के बराबर , स्विफ्ट में तो वैकल्पिक वैरिएबल प्रकार जोड़ा गया है (चर द्वारा प्रत्यय "?"):

    var aString = nil //error

बड़ा अंतर यह है कि वैकल्पिक चर सीधे मानों को संग्रहीत नहीं करते हैं (एक सामान्य ओब्ज-सी चर के रूप में) उनके पास दो राज्य होंगे : " एक मान है " या " शून्य है ":

    var aString: String? = "Hello, World!"
    aString = nil //correct, now it contains the state "has nil"

यह होने के नाते, आप विभिन्न स्थितियों में उन चर की जाँच कर सकते हैं:

if let myString = aString? {
     println(myString)
}
else { 
     println("It's nil") // this will print in our case
}

"का उपयोग करके!" प्रत्यय, आप उन में लिपटे मूल्यों तक भी पहुंच सकते हैं, केवल अगर वे मौजूद हैं । (अर्थात यह शून्य नहीं है ):

let aString: String? = "Hello, World!"
// var anotherString: String = aString //error
var anotherString: String = aString!

println(anotherString) //it will print "Hello, World!"

इसलिए आपको "उपयोग करने की आवश्यकता है?" तथा "!" और डिफ़ॉल्ट रूप से उन सभी का उपयोग न करें। (यह मेरी सबसे बड़ी घबराहट थी)

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


7

ऑब्जेक्टिव C वेरिएबल्स में बिना वैल्यू वाले 'nil' के बराबर थे (यह 'nil' वैल्यूज को 0 और झूठे के रूप में भी इस्तेमाल करना संभव था), इसलिए सशर्त स्टेटमेंट्स में वेरिएबल्स का उपयोग करना संभव था (वेरिएबल्स वैल्यूज वैसी ही हैं जैसे कि TRUE) 'और जिनका कोई मूल्य नहीं' FALSE 'के बराबर था)।

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

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

var hw = "Hello World"

यहाँ, भले ही 'hw' एक स्ट्रिंग है, लेकिन इसका उपयोग उद्देश्य C जैसे कथन में नहीं किया जा सकता है।

//This is an error

if hw

 {..}

इसके लिए इसे बनाने की आवश्यकता है,

var nhw : String? = "Hello World"

//This is correct

if nhw

 {..}

5

वैकल्पिक मूल्य आपको मूल्य की अनुपस्थिति दिखाने की अनुमति देता है। उद्देश्य-सी में SQL या NSNull में NULL की तरह थोड़ा सा। मुझे लगता है कि यह एक सुधार होगा क्योंकि आप इसे "आदिम" प्रकारों के लिए भी उपयोग कर सकते हैं।

// Reimplement the Swift standard library's optional type
enum OptionalValue<T> {
    case None
    case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)

इसके अंश: Apple Inc. "स्विफ्ट प्रोग्रामिंग लैंग्वेज।" iBooks। https://itun.es/gb/jEUH0.l


6
nilएनम स्थिरांक के लिए सिंटैक्टिक शुगर है OptionalValue<T>.None( Tजहां आप उपयोग कर रहे हैं उस संदर्भ के लिए उपयुक्त प्रकार है nil)। ?के लिए एक शॉर्टकट है OptionalValue<T>.Some(T)
रिकस्टर

4

एक वैकल्पिक का अर्थ है कि स्विफ्ट पूरी तरह से निश्चित नहीं है अगर मूल्य प्रकार से मेल खाती है: उदाहरण के लिए, इंट? इसका मतलब है कि स्विफ्ट पूरी तरह से निश्चित नहीं है कि नंबर एक इंट है या नहीं।

इसे हटाने के लिए, तीन तरीके हैं जिन्हें आप नियोजित कर सकते हैं।

1) यदि आप पूरी तरह से निश्चित हैं, तो आप इसे हटाने के लिए एक विस्मयादिबोधक चिह्न का उपयोग कर सकते हैं, जैसे:

// Here is an optional variable:

var age: Int?

// Here is how you would force unwrap it:

var unwrappedAge = age!

यदि आप एक विकल्प को बलपूर्वक खोलते हैं और यह शून्य के बराबर होता है, तो आप इस क्रैश त्रुटि का सामना कर सकते हैं:

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

यह आवश्यक रूप से सुरक्षित नहीं है, इसलिए यहां एक विधि है जो दुर्घटना को रोक सकती है यदि आप प्रकार और मूल्य के बारे में निश्चित नहीं हैं:

इस समस्या के लिए तरीके 2 और तीन सुरक्षित हैं।

2) द अनप्लान्टली अनकैप्ड ऑप्शनल

 if let unwrappedAge = age {

 // continue in here

 }

ध्यान दें कि इंट्रा टाइप अब Int के बजाय Int है?

3) गार्ड का बयान

 guard let unwrappedAge = age else { 
   // continue in here
 }

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

आपकी परियोजना के लिए शुभकामनाएं!


1

जब मैंने सीखना शुरू किया तो Swiftयह जानना बहुत मुश्किल था कि वैकल्पिक क्यों है

इस तरह से सोचते हैं। एक ऐसे वर्ग पर विचार करें Personजिसके पास दो संपत्ति हैं nameऔर company

class Person: NSObject {

    var name : String //Person must have a value so its no marked as optional
    var companyName : String? ///Company is optional as a person can be unemployed that is nil value is possible

    init(name:String,company:String?) {

        self.name = name
        self.companyName = company

    }
}

अब कुछ ऑब्जेक्ट्स बनाने देता है Person

var tom:Person = Person.init(name: "Tom", company: "Apple")//posible
var bob:Person = Person.init(name: "Bob", company:nil) // also Possible because company is marked as optional so we can give Nil

लेकिन हम पारित नहीं हो सकता Nilकरने के लिएname

var personWithNoName:Person = Person.init(name: nil, company: nil)

अब बात करते हैं कि हम क्यों उपयोग करते हैं optional?। एक स्थिति पर विचार जहां हम जोड़ना चाहते हैं की सुविधा देता है Incकी तरह कंपनी के नाम के बाद appleकिया जाएगा apple Inc। हमें Incकंपनी के नाम और प्रिंट के बाद संलग्न करना होगा।

print(tom.companyName+" Inc") ///Error saying optional is not unwrapped.
print(tom.companyName!+" Inc") ///Error Gone..we have forcefully unwrap it which is wrong approach..Will look in Next line
print(bob.companyName!+" Inc") ///Crash!!!because bob has no company and nil can be unwrapped.

अब अध्ययन करता है कि वैकल्पिक स्थान क्यों लेता है।

if let companyString:String = bob.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.

    print(companyString+" Inc") //Will never executed and no crash!!!
}

bobसाथ देता हैtom

if let companyString:String = tom.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.

    print(companyString+" Inc") //Will never executed and no crash!!!
}

और बधाई! हमने ठीक से व्यवहार किया हैoptional?

तो अहसास अंक हैं

  1. यदि संभव हो तो हम एक चर को वैकल्पिक के रूप में चिह्नित करेंगे nil
  2. अगर हम कोड चर में इस चर का उपयोग करना चाहते हैं तो आपको याद दिलाएंगे कि अगर हम उस चर के साथ उचित व्यवहार करते हैं, तो हमें इसकी जांच करनी होगी nil

थैंक यू ... हैप्पी कोडिंग


0

नीचे दिए गए कोड के साथ प्लेग्राउंड का प्रयोग करें। मुझे आशा है कि यह स्पष्ट है कि इसका उपयोग करने का वैकल्पिक और कारण क्या है।

var sampleString: String? ///Optional, Possible to be nil

sampleString = nil ////perfactly valid as its optional

sampleString = "some value"  //Will hold the value

if let value = sampleString{ /// the sampleString is placed into value with auto force upwraped.

    print(value+value)  ////Sample String merged into Two
}

sampleString = nil // value is nil and the

if let value = sampleString{

    print(value + value)  ///Will Not execute and safe for nil checking
}

//   print(sampleString! + sampleString!)  //this line Will crash as + operator can not add nil

0

से https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html :

वैकल्पिक चैनिंग एक वैकल्पिक पर गुणों, विधियों और सदस्यता को क्वेरी और कॉल करने के लिए एक प्रक्रिया है, जो वर्तमान में शून्य हो सकती है। यदि वैकल्पिक में कोई मान है, तो गुण, विधि या सबस्क्रिप्ट कॉल सफल होता है; यदि वैकल्पिक शून्य है, तो प्रॉपर्टी, मेथड या सबस्क्रिप्ट कॉल रिटर्न निल है। कई प्रश्नों को एक साथ जंजीर में डाला जा सकता है, और यदि श्रृंखला में कोई लिंक शून्य है, तो पूरी श्रृंखला इनायत से विफल हो जाती है।

गहराई से समझने के लिए, ऊपर दिए गए लिंक को पढ़ें।


0

कुंआ...

? (वैकल्पिक) इंगित करता है कि आपके चर में शून्य मान हो सकता है जबकि ! (अल्ट्रैपर) इंगित करता है कि आपके चर में रनटाइम के दौरान मेमोरी (या मान) होनी चाहिए।

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

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

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

var defaultNil : Int?  // declared variable with default nil value
println(defaultNil) >> nil  

var canBeNil : Int? = 4
println(canBeNil) >> optional(4)

canBeNil = nil
println(canBeNil) >> nil

println(canBeNil!) >> // Here nil optional variable is being unwrapped using ! mark (symbol), that will show runtime error. Because a nil optional is being tried to get value using unwrapper

var canNotBeNil : Int! = 4
print(canNotBeNil) >> 4

var cantBeNil : Int = 4
cantBeNil = nil // can't do this as it's not optional and show a compile time error

Apple डेवलपर कमेटी द्वारा यहां विस्तार से बुनियादी ट्यूटोरियल दिया गया है: वैकल्पिक चेनिंग


0

स्विफ्ट में एक वैकल्पिक एक प्रकार है जो या तो मूल्य या कोई मूल्य नहीं पकड़ सकता है। वैकल्पिक एक जोड़कर लिखा जाता है ? किसी भी प्रकार के लिए:

var name: String?

आप इस लिंक का उल्लेख गहरे में ज्ञान प्राप्त करने के लिए कर सकते हैं: https://medium.com/@agoiabeladeyemi/optionals-in-swift-2b141f12f870


-1

यहाँ स्विफ्ट में एक समान वैकल्पिक घोषणा है:

var middleName: String?

यह घोषणापत्र स्ट्रिंग के मध्य नाम का एक चर बनाता है। स्ट्रिंग चर प्रकार के बाद प्रश्न चिह्न (?) इंगित करता है कि मध्यनाम चर में एक मान हो सकता है जो या तो स्ट्रिंग या शून्य हो सकता है। इस कोड को देखने वाला कोई भी व्यक्ति तुरंत जानता है कि मध्यनाम शून्य हो सकता है। यह स्व-दस्तावेजीकरण है!

यदि आप एक वैकल्पिक स्थिर या चर के लिए एक प्रारंभिक मान निर्दिष्ट नहीं करते हैं (जैसा कि ऊपर दिखाया गया है) तो मान आपके लिए शून्य पर सेट हो जाता है। यदि आप पसंद करते हैं, तो आप स्पष्ट रूप से प्रारंभिक मूल्य को शून्य पर सेट कर सकते हैं:

var middleName: String? = nil

नीचे दिए गए वैकल्पिक पढ़ने के लिए और अधिक विस्तार के लिए लिंक

http://www.iphonelife.com/blog/31369/swift-101-working-swifts-new-optional-values


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