स्विफ्ट: गार्ड लेट बनाम अगर लेट


132

मैं स्विफ्ट में Optionals के बारे में पढ़ रहा हूं, और मैंने ऐसे उदाहरण देखे हैं जहां if letयह जांचने के लिए उपयोग किया जाता है कि क्या कोई ऑप्शनल एक मान रखता है, और यदि ऐसा होता है - तो अनकैप्ड वैल्यू के साथ कुछ करें।

हालाँकि, मैंने देखा है कि स्विफ्ट 2.0 में guard letज्यादातर कीवर्ड का उपयोग किया जाता है। मुझे आश्चर्य है कि क्या if letस्विफ्ट 2.0 से हटा दिया गया है या यदि यह अभी भी उपयोग किया जाना संभव है।

मैं अपने प्रोग्राम हैं जो शामिल बदलना चाहिए if letकरने के लिए guard let?

जवाबों:


164

if letऔर guard letसमान सेवा, लेकिन अलग-अलग उद्देश्य।

"और" मामले guardको मौजूदा दायरे से बाहर होना चाहिए। आम तौर पर इसका मतलब है कि इसे returnप्रोग्राम को कॉल या गर्भपात करना होगा । guardसमारोह के बाकी हिस्सों के घोंसले के बिना जल्दी वापसी प्रदान करने के लिए उपयोग किया जाता है।

if letइसके दायरे में घोंसले हैं, और इसके लिए कुछ विशेष की आवश्यकता नहीं है। यह कर सकते हैं returnया नहीं।

सामान्य तौर पर, यदि if-letब्लॉक बाकी फ़ंक्शन करने वाला था, या इसके elseक्लॉज़ में एक returnया गर्भपात होगा, तो आपको guardइसके बजाय उपयोग करना चाहिए । इसका अक्सर मतलब होता है (कम से कम मेरे अनुभव में), जब संदेह में, guardआमतौर पर बेहतर जवाब होता है। लेकिन वहाँ बहुत सारी स्थितियाँ हैं जहाँ if letअभी भी उपयुक्त है।


38
if letजब non-nilमामला वैध हो तब उपयोग करें । guardजब nilमामला किसी प्रकार की त्रुटि का प्रतिनिधित्व करता है तो उपयोग करें ।
बॉलपॉइंटबैन

4
@ बॉलपॉइंट तब मैं इससे सहमत नहीं हूं। ऐसे कई मामले हैं जहां guardकोई त्रुटि नहीं होने पर भी उचित है। कभी-कभी इसका मतलब सिर्फ इतना है कि कुछ नहीं करना है। उदाहरण के लिए, एक positionTitleविधि हो सकती है guard if let title = title else {return}। शीर्षक वैकल्पिक हो सकता है, जिस स्थिति में यह त्रुटि नहीं है। लेकिन फिर guard letभी उचित है।
रोब नेपियर

1
हाँ; मेरा मतलब था कि टिप्पणी में गार्ड चलो।
रोब नेपियर

1
दूसरे शब्दों में, "गार्ड लेट" का उपयोग तब किया जाता है जब कोड 99% है और अन्य सशर्त का उपयोग नहीं करने के बारे में सुनिश्चित है; दूसरे हाथ में, "if let" जब कोड 50 - 50 (उदाहरण) है, तो किसी अन्य शर्त का उपयोग करने के लिए।
चिनो पान

1
द्वारा विभाजित चर if letकेवल दायरे के अंदर दिखाई देता हैif let । द्वारा विभाजित चर guard letबाद में दिखाई देता है। तो यह वैकल्पिक मूल्यों को भी बांधने के लिए गार्ड का उपयोग करने के लिए समझ में आता है।
धनुषयमन

105

गार्ड स्पष्टता में सुधार कर सकते हैं

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

func icon() -> UIImage {
    guard let image = UIImage(named: "Photo") else {
        return UIImage(named: "Default")! //This is your fallback
    }
    return image //-----------------you're always expecting/hoping this to happen
}

यदि आप उपरोक्त कोड को if-let के साथ लिखते हैं तो यह पढ़ने वाले डेवलपर को बताता है कि यह 50-50 से अधिक है। लेकिन अगर आप गार्ड का उपयोग करते हैं तो आप अपने कोड में स्पष्टता जोड़ते हैं और इसका मतलब है कि मैं इस समय के 95% काम करने की उम्मीद करता हूं ... अगर यह कभी विफल रहा, तो मुझे नहीं पता कि यह क्यों होगा; यह बहुत संभावना नहीं है ... लेकिन इसके बजाय इस डिफ़ॉल्ट छवि का उपयोग करें या शायद सिर्फ एक सार्थक संदेश के साथ दावा करें कि क्या गलत हुआ!

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

  • जब आप सकारात्मक शाखा में महत्वपूर्ण गणना करते हैं, तो ifएक guardबयान से प्रतिक्षेपक और elseक्लॉज में फ़ॉलबैक मान लौटाता है

प्रेषक: एरिका सदुन की स्विफ्ट स्टाइल पुस्तक

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

guard​ ​let​ image =UIImage(named: selectedImageName) else { // YESSSSSS
     assertionFailure("Missing ​​\(​selectedImageName​)​​ asset") 
     return
} 

guard​ ​let​ image =UIImage(named: selectedImageName) else { // NOOOOOOO
​     ​return 
}

प्रेषक: एरिका सदुन की स्विफ्ट शैली की किताब + कुछ संशोधन

(आप if-letएस के लिए जोर / पूर्व शर्त का उपयोग नहीं करेंगे । यह सिर्फ सही नहीं लगता है)

गार्ड का उपयोग करना आपको कयामत के पिरामिड से बचने के लिए स्पष्टता में सुधार करने में भी मदद करता है । देखें नितिन का जवाब


गार्ड एक नया चर बनाता है

एक महत्वपूर्ण अंतर यह है कि मेरा मानना ​​है कि किसी ने अच्छी तरह से समझाया नहीं है।

दोनों guard letऔर हालांकि चर को if let खोलना

साथ guard letआप बना रहे हैं एक नया वेरिएबल कि मौजूद बाहर elseबयान।

साथ if letआप नहीं बना रहे हैं किसी भी नए चर के बाद किसी और बयान, आप केवल प्रवेश कोड ब्लॉक करता है, तो वैकल्पिक गैर शून्य होता है। नव निर्मित चर कोड ब्लॉक के अंदर ही मौजूद है , उसके बाद नहीं!

guard let:

func someFunc(blog: String?) {

    guard let blogName = blog else {
        print("some ErrorMessage")
        print(blogName) // will create an error Because blogName isn't defined yet
        return
    }
    print(blogName) // You can access it here ie AFTER the guard statement!!

    //And if I decided to do 'another' guard let with the same name ie 'blogName' then I would create an error!
    guard let blogName = blog else { // errorLine: Definition Conflicts with previous value.
        print(" Some errorMessage")
        return
    }
    print(blogName)
}

if-let:

func someFunc(blog: String?) {


    if let blogName1 = blog {
        print(blogName1) // You can only access it inside the code block. Outside code block it doesn't exist!
    }
    if let blogName1 = blog { // No Error at this line! Because blogName only exists inside the code block ie {}
        print(blogName1)
    }
}

अधिक जानकारी के if letलिए देखें: वैकल्पिक बाध्यकारी के पुनर्वितरण में त्रुटि क्यों नहीं होती है


गार्ड को गुंजाइश बाहर निकलने की आवश्यकता है

(रोब नेपियर के उत्तर में भी उल्लेख किया गया है):

आपने एक फंक के अंदरguard परिभाषित किया होगा । यदि कोई शर्त पूरी नहीं हुई तो इसका मुख्य उद्देश्य / वापसी / निकास गुंजाइश को रोकना है :

var str : String?

guard let blogName1 = str else {
    print("some error")
    return // Error: Return invalid outside of a func
}
print (blogName1)

के लिए if letआप किसी भी समारोह के अंदर यह करने की जरूरत नहीं है:

var str : String?    
if let blogName1 = str {
   print(blogName1) // You don't get any errors!
}

guard बनाम if

यह ध्यान देने योग्य है कि इस प्रश्न को guard letबनाम if letऔर guardबनाम के रूप में देखना अधिक उपयुक्त है if

एक स्टैंडअलोन ifकिसी भी अलौकिक नहीं करता है, न ही एक स्टैंडअलोन करता है guard। नीचे उदाहरण देखें। यदि मूल्य है तो यह जल्दी बाहर नहीं निकलता है nil। कोई वैकल्पिक मूल्य नहीं हैं। यदि कोई शर्त पूरी नहीं हुई तो यह जल्दी बाहर निकल जाता है।

let array = ["a", "b", "c"]
func subscript(at index: Int) -> String?{
   guard index > 0, index < array.count  else { return nil} // exit early with bad index
   return array[index]
}

46

कब इस्तेमाल करना है if-letऔर कब इस्तेमाल करना है guardयह अक्सर स्टाइल का सवाल होता है।

कहो कि आपके पास func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Intऔर वैकल्पिक आइटम हैं ( var optionalArray: [SomeType]?), और आपको या 0तो वापस लौटने की आवश्यकता है यदि सरणी है nil(नहीं-सेट) या countयदि सरणी का मान है (सेट है)।

आप इसे इस तरह से लागू कर सकते हैं if-let:

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        if let array = optionalArray {
            return array.count
        }
        return 0
    }

या इस तरह का उपयोग कर guard:

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        guard let array = optionalArray else {
            return 0
        }
        return array.count
    }

उदाहरण कार्यात्मक रूप से समान हैं।

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

if-letएस के एक गुच्छा को घोंसला बनाने के बजाय, जैसा कि आप सत्यापन को समाप्त करने के करीब पहुंचते हैं, "सफलता का रास्ता" और अब सफलतापूर्वक बाध्य विकल्प सभी विधि के मुख्य दायरे में हैं, क्योंकि विफलता के रास्ते सभी पहले ही वापस आ चुके हैं।


30

मैं कुछ (अडॉप्ट किए गए) कोड के साथ गार्ड स्टेटमेंट की उपयोगिता को समझाने की कोशिश करूंगा।

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

यदि कोई भी टेक्स्टफ़िल्ड मान्य पाठ नहीं है, तो उसे उस क्षेत्र को पहले बनाना चाहिए।

यहाँ अडॉप्टिमाइज्ड कोड है:

//pyramid of doom

func validateFieldsAndContinueRegistration() {
    if let firstNameString = firstName.text where firstNameString.characters.count > 0{
        if let lastNameString = lastName.text where lastNameString.characters.count > 0{
            if let emailString = email.text where emailString.characters.count > 3 && emailString.containsString("@") && emailString.containsString(".") {
                if let passwordString = password.text where passwordString.characters.count > 7{
                    // all text fields have valid text
                    let accountModel = AccountModel()
                    accountModel.firstName = firstNameString
                    accountModel.lastName = lastNameString
                    accountModel.email = emailString
                    accountModel.password = passwordString
                    APIHandler.sharedInstance.registerUser(accountModel)
                } else {
                    password.becomeFirstResponder()
                }
            } else {
                email.becomeFirstResponder()
            }
        } else {
            lastName.becomeFirstResponder()
        }
    } else {
        firstName.becomeFirstResponder()
    }
}

आप ऊपर देख सकते हैं, कि सभी स्ट्रिंग्स (फर्स्टनामेस्ट्रिंग, लास्ट नेमस्ट्रिंग आदि) केवल इफ स्टेटमेंट के दायरे में ही उपलब्ध हैं। इसलिए यह "कयामत का पिरामिड" बनाता है और इसके साथ कई मुद्दे हैं, जिनमें पठनीयता और आसपास की चीजों को आसानी से शामिल करना (यदि फ़ील्ड के आदेश को बदल दिया गया है, तो आपको इस कोड को फिर से लिखना होगा)

गार्ड स्टेटमेंट के साथ (नीचे दिए गए कोड में), आप देख सकते हैं कि ये तार बाहर उपलब्ध {}हैं और सभी क्षेत्रों के मान्य होने पर उपयोग किए जाते हैं।

// guard let no pyramid of doom
func validateFieldsAndContinueRegistration() {

guard let firstNameString = firstName.text where firstNameString.characters.count > 0 else {
            firstName.becomeFirstResponder()
            return
        }
guard let lastNameString = lastName.text where lastNameString.characters.count > 0 else {
            lastName.becomeFirstResponder()
            return
        }
guard let emailString = email.text where 
        emailString.characters.count > 3 &&
        emailString.containsString("@") && 
        emailString.containsString(".") else {
            email.becomeFirstResponder()
            return
        }
guard let passwordString = password.text where passwordString.characters.count > 7 else {
            password.becomeFirstResponder()
            return
        }

// all text fields have valid text
    let accountModel = AccountModel()
    accountModel.firstName = firstNameString
    accountModel.lastName = lastNameString
    accountModel.email = emailString
    accountModel.password = passwordString
    APIHandler.sharedInstance.registerUser(accountModel)
}

यदि फ़ील्ड का क्रम बदलता है, तो कोड की संबंधित पंक्तियों को ऊपर या नीचे ले जाएँ, और आप जाने के लिए अच्छे हैं।

यह एक बहुत ही सरल व्याख्या और उपयोग का मामला है। उम्मीद है की यह मदद करेगा!


14

बुनियादी अंतर

गार्ड रहने दो

  1. स्कोप से जल्दी अस्तित्व की प्रक्रिया
  2. रिटर्न, थ्रो आदि जैसे स्कोर की आवश्यकता है।
  3. एक नया वैरिएबल बनाएं जो दायरे से बाहर हो सकता है।

अगर रहने दो

  1. दायरे से बाहर नहीं जा सकते।
  2. बयान वापस करने की आवश्यकता नहीं है। लेकिन हम लिख सकते हैं

नोट: दोनों का उपयोग वैकल्पिक चर को हटाने के लिए किया जाता है।



2

रक्षक

  • guardयदि एक या अधिक शर्तें पूरी नहीं होती हैं, तो एक बयान को प्रोग्राम कंट्रोल को एक दायरे से बाहर स्थानांतरित करने के लिए उपयोग किया जाता है।

  • किसी guardस्टेटमेंट में किसी भी हालत का मान टाइप Bool या टाइप किया हुआ होना चाहिए Bool। शर्त एक वैकल्पिक बाध्यकारी घोषणा भी हो सकती है।

एक गार्ड स्टेटमेंट के निम्न रूप हैं:

guard condition else {
    //Generally return
}

अगर रहने दो

  • वैकल्पिक बंधन के रूप में भी लोकप्रिय है ।
  • वैकल्पिक ऑब्जेक्ट तक पहुंचने के लिए हम उपयोग करते हैं if let
if let roomCount = optionalValue {
    print("roomCount available")
} else {
    print("roomCount is nil")
}

1

मैं बॉब के साथ तेजी से यह सीखा है ..

टाइप-एल्स-इफ

 func checkDrinkingAge() {
      let canDrink = true

     if canDrink {
        print("You may enter")
       // More Code
        // More Code
      // More Code

         } else {
         // More Code
    // More Code
    // More Code
    print("Let me take you to the jail")
          }
     }

एल्स-इफ के साथ मुद्दे

  1. नेस्टेड कोष्ठक
  2. त्रुटि संदेश को देखने के लिए हर पंक्ति को पढ़ना होगा

गार्ड स्टेटमेंट एक गार्ड ब्लॉक केवल तभी चलता है जब स्थिति झूठी होती है, और यह रिटर्न के माध्यम से फ़ंक्शन से बाहर निकल जाएगा। यदि स्थिति सही है, तो स्विफ्ट गार्ड ब्लॉक की उपेक्षा करता है। यह एक प्रारंभिक निकास और कम कोष्ठक प्रदान करता है। +

func checkDrinkProgram() {
       let iCanDrink = true

           guard iCanDrink else {
        // if iCanDrink == false, run this block
         print("Let's me take you to the jail")
          return
        }

         print("You may drink")
           // You may move on
                  // Come on.
                 // You may leave
                // You don't need to read this.
                 // Only one bracket on the bottom: feeling zen.
       }

एल्प-इफ के साथ अनप्रेड ऑप्शनल

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

var publicName: String? = "Bob Lee"
var publicPhoto: String? = "Bob's Face"
var publicAge: Int? = nil

सबसे बुरा सपना

func unwrapOneByOne() {
         if let name = publicName {
              if let photo = publicPhoto {
                     if let age = publicAge {
                        print("Bob: \(name), \(photo), \(age)")
                                  } else {
                          print("age is mising")
                           }
                  } else {
                      print("photo is missing")
                         }
                  } else {
                        print("name is missing")
                         }
                  }

उपरोक्त कोड निश्चित रूप से काम करता है लेकिन DRY सिद्धांत का उल्लंघन करता है। यह अत्याचारी है। हमें इसे तोड़ दो। +

थोड़ा बेहतर कोड नीचे दिए गए कोड से अधिक पठनीय है। +

func unwrapBetter() {
         if let name = publicName {
       print("Yes name")
                   } else {
               print("No name")
        return
      }

         if let photo = publicPhoto {
             print("Yes photo")
            } else {
           print("No photo")
       return
             }

        if let age = publicAge {
            print("Yes age")
                      } else {
                print("No age")
            return
                           }
     }

गार्ड के साथ अनवैप - और-अगर बयान गार्ड के साथ बदले जा सकते हैं। +

 func unwrapOneByOneWithGuard() {
             guard let name = publicName else {
                  print("Name missing")
              return
                                        }

              guard let photo = publicPhoto else {
              print("Photo missing")
                return
                                            }

                  guard let age = publicAge else {
                   print("Age missing")
                                     return
                                                 }
                 print(name)
                 print(photo)
                 print(age)
         }

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

func unwrap() {
  if let name = publicName, let photo = publicPhoto, let age = publicAge {
    print("Your name is \(name). I see your face right here, \(photo), you are \(age)")
  } else {
    // if any one of those is missing
    print("Something is missing")
  }
}

ध्यान रखें कि जब आप एक ही बार में कई वैकल्पिकों को खोलते हैं, तो आप पहचान नहीं सकते हैं जिसमें नील शामिल हैं

गार्ड के साथ कई वैकल्पिकों को अनप्लग करें , हमें गार्ड को दूसरे पर इस्तेमाल करना चाहिए-अगर। +

func unwrapWithGuard() {
  guard let name = publicName, let photo = publicPhoto, let age = publicAge else {
    // if one or two of the variables contain "nil"
    print("Something is missing")
    return
  }

  print("Your name is \(name). I see your, \(photo). You are \(age).")
  // Animation Logic
  // Networking
  // More Code, but still zen
}

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