स्विफ्ट: नील के लिए वैकल्पिक परीक्षण


137

मैं Xcode 6 बीटा 4 का उपयोग कर रहा हूं। मेरे पास यह अजीब स्थिति है, जहां मैं यह नहीं जान सकता कि वैकल्पिक के लिए उचित परीक्षण कैसे किया जाए।

यदि मेरे पास एक वैकल्पिक xyz है, तो परीक्षण करने का सही तरीका है:

if (xyz) // Do something

या

if (xyz != nil) // Do something

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

मेरा विशिष्ट उदाहरण GData XML पार्सर का उपयोग तेज करने के लिए किया गया है:

let xml = GDataXMLDocument(
    XMLString: responseBody,
    options: 0,
    error: &xmlError);

if (xmlError != nil)

यहाँ, अगर मैंने अभी किया:

if xmlError

यह हमेशा सच होगा। हालाँकि, अगर मैं:

if (xmlError != nil)

तब यह काम करता है (जैसा कि यह उद्देश्य-सी में कैसे काम करता है)।

क्या GData XML के साथ कुछ है और जिस तरह से यह वैकल्पिक व्यवहार करता है कि मैं गायब हूँ?


4
क्या हम आपके अप्रत्याशित मामले और त्रुटि मामलों के लिए एक पूर्ण उदाहरण देख सकते हैं, कृपया? (और मुझे पता है कि यह कठिन है, लेकिन सशर्त चारों ओर कोष्ठक खोने शुरू करने की कोशिश करें!)
मैट गिब्सन

1
इसे Xcode 6 बीटा 5 में बदला गया है
newacct


मैंने अनपेक्षित मामले के साथ सवाल को अपडेट किया।
TNG

मैंने अभी तक बीटा 5 में अपडेट नहीं किया है। मैं जल्द ही ऐसा करूंगा; देख कर अच्छा लगा ?? स्विफ्ट में, और अधिक सुसंगत वैकल्पिक व्यवहार।
15

जवाबों:


172

Xcode Beta 5 में, वे अब आपको ऐसा नहीं करने देंगे:

var xyz : NSString?

if xyz {
  // Do something using `xyz`.
}

यह एक त्रुटि पैदा करता है:

प्रोटोकॉल 'बूलियन टाइपप्रोटोकॉल' के अनुरूप नहीं है

आपको इनमें से एक फॉर्म का उपयोग करना है:

if xyz != nil {
   // Do something using `xyz`.
}

if let xy = xyz {
   // Do something using `xy`.
}

5
क्या कोई इस बात पर विस्तार दे सकता है कि xyz == नील काम क्यों नहीं कर रहा है?
क्रिस्टोफ

दूसरा उदाहरण पढ़ना चाहिए: // xy का उपयोग करके कुछ करें (जो कि दो वेरिएंट के बीच उपयोग के मामलों में मुख्य अंतर है)
Alper

@Christoph: त्रुटि संदेश यह है कि निरंतर 'xyz' का प्रयोग होने से पहले किया जाता है। मुझे लगता है कि आपको xyz की घोषणा की रेखा के अंत में '= nil' को जोड़ना होगा।
user3207158

उन लोगों के लिए जो मैं हूं के रूप में तेजी से नए हैं और सोच रहे हैं: आपको अभी भी अगर ब्लॉक के अंदर xyz खोलना है। हालाँकि, यह सुरक्षित है, भले ही आप अनफ्रेंड
उमर

@ उमर यह दूसरे रूप की सुंदरता है, आप इसे खोलना नहीं है ब्लॉक के अंदर xy का उपयोग करें।
एरिक डोरेनबर्ग

24

किसी ifशर्त के अंदर एक भिन्न नाम वाले चर को निर्दिष्ट करने के बजाय, अन्य उत्तरों को जोड़ने के लिए :

var a: Int? = 5

if let b = a {
   // do something
}

आप इस तरह एक ही चर नाम का पुन: उपयोग कर सकते हैं:

var a: Int? = 5

if let a = a {
    // do something
}

यह आपको रचनात्मक चर नामों से बाहर निकलने में मदद कर सकता है ...

यह परिवर्तनशील छायांकन का लाभ उठाता है जो स्विफ्ट में समर्थित है।


18

वैकल्पिक उपयोग करने के सबसे प्रत्यक्ष तरीकों में से एक निम्नलिखित है:

उदाहरण के लिए मान xyzलेना वैकल्पिक प्रकार का है Int?

if let possXYZ = xyz {
    // do something with possXYZ (the unwrapped value of xyz)
} else {
    // do something now that we know xyz is .None
}

इस तरह आप दोनों का परीक्षण कर सकते हैं यदि xyzकोई मान शामिल है और यदि हां, तो तुरंत उस मान के साथ काम करें।

आपकी संकलक त्रुटि के संबंध में, प्रकार UInt8वैकल्पिक नहीं है (नोट संख्या '?') और इसलिए इसे परिवर्तित नहीं किया जा सकता है nil। सुनिश्चित करें कि आप जिस चर के साथ काम कर रहे हैं, वह एक जैसा व्यवहार करने से पहले एक वैकल्पिक है।


1
मुझे यह तरीका बुरा लग रहा है क्योंकि मैं एक नया चर (निरंतर) बनाता हूं अनावश्यक रूप से, ans ने एक नया नाम बनाया है जो कि अधिकांश समय पहले की तुलना में सबसे खराब होने वाला है। मुझे लिखने के लिए और पाठक के लिए अधिक समय लगता है।
लोमबास

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

@ gnasher729 लेकिन क्या होगा यदि आप केवल दूसरे भाग का उपयोग करना चाहते हैं
ब्रैड थॉमस

15

स्विफ्ट 3.0, 4.0

नील के लिए वैकल्पिक रूप से जाँच के दो तरीके हैं। यहां उनके बीच तुलना के साथ उदाहरण दिए गए हैं

1. अगर होने दो

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

इसके अलावा, अगर xशून्य नहीं है, तो बंद को निष्पादित किया x_valजाएगा और अंदर उपलब्ध होगा। अन्यथा दूसरा बंद शुरू हो जाता है।

if let x_val = x, x_val > 5 {
    //x_val available on this scope
} else {

}

2. रक्षक दो

guard letइसी तरह के काम कर सकते हैं। यह मुख्य उद्देश्य है कि इसे तार्किक रूप से अधिक उचित बनाया जाए। यह कहने जैसा है कि सुनिश्चित करें कि चर शून्य नहीं है, अन्यथा फ़ंक्शन रोकेंguard letके रूप में अतिरिक्त हालत जाँच भी कर सकते हैं if let

अंतर यह है कि अलिखित मान उसी दायरे पर उपलब्ध होगा guard let, जैसा कि नीचे टिप्पणी में दिखाया गया है। यह भी बात किसी और बंद करने में, कार्यक्रम वर्तमान क्षेत्र से बाहर निकलने नहीं है की ओर जाता है से return, breakआदि

guard let x_val = x, x_val > 5 else {
    return
}
//x_val available on this scope

11

स्विफ्ट प्रोग्रामिंग गाइड से

यदि स्टेटमेंट्स और फोर्स्ड अनवापिंग

आप एक वैकल्पिक विवरण का मान रखते हैं या नहीं यह जानने के लिए आप एक कथन का उपयोग कर सकते हैं। यदि किसी वैकल्पिक का मान होता है, तो यह सत्य का मूल्यांकन करता है; यदि इसका कोई मूल्य नहीं है, तो यह गलत का मूल्यांकन करता है।

तो ऐसा करने का सबसे अच्छा तरीका है

// swift > 3
if xyz != nil {}

और यदि आप xyzif स्टेटमेंट में उपयोग कर रहे हैं। यदि आप xyzनिरंतर वेरिएबल में स्टेटमेंट में अनचेक कर सकते हैं । तो यदि आपको उस स्टेटमेंट में हर जगह को अनफ्रैप करने की आवश्यकता नहीं है, जहां xyzउपयोग किया जाता है।

if let yourConstant = xyz{
      //use youtConstant you do not need to unwrap `xyz`
}

इस सम्मेलन के द्वारा सुझाव दिया गया है appleऔर इसके बाद देव्लोपर्स का पालन किया जाएगा।


2
स्विफ्ट 3 में आपको करना होगा if xyz != nil {...}
23

स्विफ्ट में 3 वैकल्पिक बूलियन के रूप में इस्तेमाल नहीं किया जा सकता है। पहला क्योंकि यह एक सी-आइसम है जो पहले कभी भी भाषा में नहीं होना चाहिए था, और दूसरा क्योंकि यह वैकल्पिक बूल के साथ पूर्ण भ्रम का कारण बनता है।
gnasher729

9

यद्यपि आपको अभी भी या तो स्पष्ट रूप से एक वैकल्पिक की तुलना करनी चाहिए nilया वैकल्पिक बाइंडिंग का उपयोग इसके अतिरिक्त मूल्य निकालने के लिए करना चाहिए (अर्थात वैकल्पिक रूप से इसे बूलियन मानों में परिवर्तित नहीं किया गया है), यह ध्यान देने योग्य है कि स्विफ्ट 2 ने काम करने के दौरान कयामत के पिरामिड से बचने में मदद करने के लिए guardबयान जोड़ा है। कई वैकल्पिक मूल्यों के साथ।

दूसरे शब्दों में, आपके विकल्पों में अब स्पष्ट रूप से जाँच शामिल है nil:

if xyz != nil {
    // Do something with xyz
}

वैकल्पिक बाध्यकारी:

if let xyz = xyz {
    // Do something with xyz
    // (Note that we can reuse the same variable name)
}

और guardकथन:

guard let xyz = xyz else {
    // Handle failure and then exit this code block
    // e.g. by calling return, break, continue, or throw
    return
}

// Do something with xyz, which is now guaranteed to be non-nil

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

if let abc = abc {
    if let xyz = xyz {
        // Do something with abc and xyz
    }        
}

आप guardबयानों के साथ इस घोंसले के शिकार से बच सकते हैं :

guard let abc = abc else {
    // Handle failure and then exit this code block
    return
}

guard let xyz = xyz else {
    // Handle failure and then exit this code block
    return
}

// Do something with abc and xyz

1
जैसा कि ऊपर उल्लेख किया गया है, आप नेस्टेड वैकल्पिक स्टेटमेनसेट से छुटकारा पाने के लिए भी ऐसा कर सकते हैं। लेट एबीसी = अगर एबीसी .xyz .something {}?
सुहैब

1
@ शुआब आह, सच: आप नेस्टेड प्रॉपर्टीज को जल्दी एक्सेस करने के लिए ऑप्शनल चेनिंग ( developer.apple.com/library/prerelease/content/documentation/… ) का भी इस्तेमाल कर सकते हैं। मैंने इसका उल्लेख यहां नहीं किया क्योंकि मुझे लगा कि यह मूल प्रश्न से बहुत अधिक हो सकता है।
क्रिस फ्रेडरिक

बहुत बढ़िया जवाब! लेकिन स्विफ्ट, OMG ... अभी भी प्रोग्रामर फ्रेंडली होने से एक लंबा रास्ता तय करता है!
turingtested

@turingtested धन्यवाद! वास्तव में, मुझे लगता है कि यह है भावना है कि यह आप की गारंटी देता है गलती से एक का उपयोग करने की कोशिश नहीं करेगा में प्रोग्रामर अनुकूल nilमूल्य, लेकिन मैं मानता हूँ कि सीखने की अवस्था एक बिट खड़ी है। :)
क्रिस फ्रेडरिक

4

स्विफ्ट 5 प्रोटोकॉल एक्सटेंशन

यहां प्रोटोकॉल एक्सटेंशन का उपयोग करने का तरीका दिया गया है ताकि आप एक वैकल्पिक नील जांच को आसानी से इनलाइन कर सकें:

import Foundation

public extension Optional {

    var isNil: Bool {

        guard case Optional.none = self else {
            return false
        }

        return true

    }

    var isSome: Bool {

        return !self.isNil

    }

}

प्रयोग

var myValue: String?

if myValue.isNil {
    // do something
}

if myValue.isSome {
    // do something
}

मैंने इस उत्तर पर कुछ कम किया है और जानना चाहूंगा कि क्यों। कम से कम टिप्पणी करें यदि आप नीचे जा रहे हैं।
ब्रॉडी रॉबर्टसन

1
संभवतया यह उस swiftअनुरूप है, pythonistasजो भाषा को किसी प्रकार की पवित्रतावादी भाषा में रखने की कोशिश करता है। मेरा स्वीकार कर लेना? मैंने अभी आपका यूटिल्स मिक्सिन में आपका कोड उठाया है।
जावदबा

2

अब आप निम्न कार्य को तेजी से कर सकते हैं जो आपको उद्देश्य-सी का थोड़ा सा हासिल करने की अनुमति देता है if nil else

if textfieldDate.text?.isEmpty ?? true {

}

2

के बजाय if, त्रिगुट ऑपरेटर काम आ सकते हैं जब आप पर है कि क्या कुछ नहीं के बराबर है आधारित एक मूल्य प्राप्त करना चाहते हैं:

func f(x: String?) -> String {
    return x == nil ? "empty" : "non-empty"
}

xyz == nilअभिव्यक्ति काम नहीं करती है, लेकिन x != nilकाम करती है। पता नहीं क्यों।
एंड्रयू

2

का उपयोग कर के अलावा एक और दृष्टिकोण ifया guardबयान वैकल्पिक बाध्यकारी करने के लिए विस्तार करने के लिए है Optionalके साथ:

extension Optional {

    func ifValue(_ valueHandler: (Wrapped) -> Void) {
        switch self {
        case .some(let wrapped): valueHandler(wrapped)
        default: break
        }
    }

}

ifValueएक क्लोजर प्राप्त करता है और इसे वैकल्पिक के रूप में मान के साथ कॉल करता है जब वैकल्पिक शून्य नहीं होता है। यह इस तरह से प्रयोग किया जाता है:

var helloString: String? = "Hello, World!"

helloString.ifValue {
    print($0) // prints "Hello, World!"
}

helloString = nil

helloString.ifValue {
    print($0) // This code never runs
}

आपको शायद ifया तो उपयोग करना चाहिए, guardलेकिन जैसे कि स्विफ्ट प्रोग्रामर द्वारा उपयोग किए जाने वाले सबसे पारंपरिक (इस प्रकार परिचित) दृष्टिकोण हैं।


2

एक विकल्प जो विशेष रूप से कवर नहीं किया गया है वह स्विफ्ट के अनदेखे मूल्य सिंटैक्स का उपयोग कर रहा है:

if let _ = xyz {
    // something that should only happen if xyz is not nil
}

मैं nilस्विफ्ट जैसी आधुनिक भाषा में जगह से बाहर महसूस करने के लिए जाँच कर रहा हूं । मुझे लगता है कि इसका कारण यह है कि nilयह मूल रूप से प्रहरी मूल्य है। हमने आधुनिक प्रोग्रामिंग में हर जगह प्रहरी के साथ बहुत दूर किया है इसलिए ऐसा nilमहसूस होता है कि इसे भी जाना चाहिए।


1

इसके अलावा आप उपयोग कर सकते हैं Nil-Coalescing Operator

nil-coalescing operator( a ?? b) एक वैकल्पिक unwraps aअगर यह होता है aमूल्य, या रिटर्न aडिफ़ॉल्ट मान bहै, तो aहै nil। अभिव्यक्ति एक हमेशा एक वैकल्पिक प्रकार की होती है। अभिव्यक्ति bको उस प्रकार से मेल खाना चाहिए जो अंदर संग्रहीत है a

let value = optionalValue ?? defaultValue

यदि optionalValueहै nil, तो यह स्वचालित रूप से मान प्रदान करता हैdefaultValue


मुझे वह पसंद है, क्योंकि यह डिफ़ॉल्ट मान निर्दिष्ट करने का आसान विकल्प देता है।
thowa

0
var xyz : NSDictionary?

// case 1:
xyz = ["1":"one"]
// case 2: (empty dictionary)
xyz = NSDictionary() 
// case 3: do nothing

if xyz { NSLog("xyz is not nil.") }
else   { NSLog("xyz is nil.")     }

इस परीक्षण ने सभी मामलों में उम्मीद के मुताबिक काम किया। BTW, आपको कोष्ठक की आवश्यकता नहीं है ()


2
मामले ओपी के बारे में चिंतित है: if (xyz != nil)
zaph

0

यदि आपके पास सशर्त हैं और वे अनचाहे और तुलना करना चाहते हैं, तो यौगिक बूलियन अभिव्यक्ति के शॉर्ट-सर्किट मूल्यांकन का लाभ उठाने के बारे में कैसे

if xyz != nil && xyz! == "some non-nil value" {

}

दी गई, यह अन्य सुझाए गए पदों में से कुछ के रूप में पठनीय नहीं है, लेकिन काम किया जाता है और अन्य सुझाए गए समाधानों की तुलना में कुछ हद तक सफल होता है।

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