स्विफ्ट का गार्ड कीवर्ड


197

स्विफ्ट 2 ने guardकीवर्ड पेश किया , जिसका उपयोग यह सुनिश्चित करने के लिए किया जा सकता है कि विभिन्न डेटा जाने के लिए तैयार है। एक उदाहरण जो मैंने इस वेबसाइट पर देखा है वह एक सबमिट किए गए फ़ंक्शन को प्रदर्शित करता है:

func submitTapped() {
    guard username.text.characters.count > 0 else {
        return
    }

    print("All good")
}

मैं सोच रहा था कि क्या guardयह किसी भी ifहालत में पुराने जमाने के तरीके का उपयोग करने से अलग है। क्या यह लाभ देता है, जिसे आप एक साधारण जांच का उपयोग करके प्राप्त नहीं कर सकते हैं?



देखें नीचे दिए गए लिंक medium.com/@pvpriya7/swift-guard-18e59c50c624
प्रियंका वी

जवाबों:


368

इस लेख को पढ़कर मैंने गार्ड के उपयोग से बहुत लाभ देखा

यहाँ आप एक उदाहरण के साथ गार्ड के उपयोग की तुलना कर सकते हैं:

यह बिना गार्ड वाला हिस्सा है:

func fooBinding(x: Int?) {
    if let x = x where x > 0 {
        // Do stuff with x
        x.description
    }

    // Value requirements not met, do something
}
  1. यहां आप सभी शर्तों के भीतर अपना वांछित कोड डाल रहे हैं

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

इसे साफ करने का तरीका यह है कि आप अपने प्रत्येक चेक को पहले करें, और यदि कोई मिले तो उससे बाहर निकलें। इससे यह समझने में आसानी होती है कि कौन सी स्थितियां इस फ़ंक्शन से बाहर निकलेंगी।

लेकिन अब हम गार्ड का उपयोग कर सकते हैं और हम देख सकते हैं कि कुछ मुद्दों को हल करना संभव है:

func fooGuard(x: Int?) {
    guard let x = x where x > 0 else {
        // Value requirements not met, do something
        return
    }

    // Do stuff with x
    x.description
}
  1. अपनी मनचाही शर्त के लिए जाँच करना, न कि आप जो चाहते हैं। यह फिर से एक मुखर के समान है। यदि शर्त पूरी नहीं होती है, तो गार्ड का दूसरा बयान चलाया जाता है, जो फ़ंक्शन से बाहर हो जाता है।
  2. यदि स्थिति गुजरती है, तो यहां वैकल्पिक वैरिएबल स्वचालित रूप से आपके लिए उस दायरे के भीतर अपरिवर्तित रहता है जिसे गार्ड स्टेटमेंट कहा जाता था - इस मामले में, फूगार्ड (_ :) फ़ंक्शन।
  3. आप जल्दी खराब मामलों की जाँच कर रहे हैं, जिससे आपका कार्य अधिक पठनीय और बनाए रखने में आसान हो जाता है

यह समान पैटर्न गैर-वैकल्पिक मानों के लिए भी सही है:

func fooNonOptionalGood(x: Int) {
    guard x > 0 else {
        // Value requirements not met, do something
        return
    }

    // Do stuff with x
}

func fooNonOptionalBad(x: Int) {
    if x <= 0 {
        // Value requirements not met, do something
        return
    }

    // Do stuff with x
}

यदि आपके पास अभी भी कोई प्रश्न है तो आप पूरे लेख को पढ़ सकते हैं: स्विफ्ट गार्ड स्टेटमेंट।

समेट रहा हु

और अंत में, पढ़ने और परीक्षण में मैंने पाया कि यदि आप किसी वैकल्पिक को खोलने के लिए गार्ड का उपयोग करते हैं,

उन अपरिवर्तित मूल्य आपके आसपास के कोड ब्लॉक के बाकी हिस्सों में उपयोग करने के लिए आपके पास रहते हैं

guard let unwrappedName = userName else {
    return
}

print("Your username is \(unwrappedName)")

यहां अनरैप्ड वैल्यू केवल अगर ब्लॉक के अंदर उपलब्ध होगी

if let unwrappedName = userName {
    print("Your username is \(unwrappedName)")
} else {
    return
}

// this won't work – unwrappedName doesn't exist here!
print("Your username is \(unwrappedName)")

3
अरे @ एरिक आपने एक बेहतरीन पोस्ट किया! इसे समझने में इतना आसान बनाने के लिए आपका धन्यवाद!
जोर्ज कासारिएगो

1
मैं NSError को अलिखित करने के लिए गार्ड का उपयोग कर रहा हूं। लेकिन जब मैं इसे गार्ड के दायरे में उपयोग करने की कोशिश करता हूं (उदाहरण के लिए कुछ कॉलबैक में त्रुटि पारित करने के लिए) तो यह कहता है कि "गार्ड की स्थिति में घोषित चर इसके शरीर में उपयोग करने योग्य नहीं है"। क्या इसका कोई मतलब है? धन्यवाद
Gerych

6
@GeRyCh एक गार्ड स्टेटमेंट में अलिखित है, उस वैरिएबल को गार्ड स्टेटमेंट के बाद के लिए उपलब्ध करता है , उसके भीतर नहीं। मुझे इसकी आदत डालने में थोड़ा समय लगा।
डोनलैला

2
यहां गार्ड का उपयोग करके वैकल्पिक रूप से वैकल्पिक रूप से खोलना करने पर एक और उत्कृष्ट लेख है । इसे अच्छी तरह से चूसता है।
Doches

let x = x where x > 0क्या इसका मतलब है कि आपने अपने वैकल्पिक बंधन में एक और शर्त जोड़ दी है? मेरा मतलब है कि यह थोड़ा अलग हैif let constantName = someOptional { statements }
हनी

36

इसके विपरीत if, guardवैरिएबल बनाता है जिसे इसके ब्लॉक के बाहर से एक्सेस किया जा सकता है। यह बहुत कुछ खोलना उपयोगी है Optional


24

वास्तव में दो बड़े लाभ हैं guard। एक कयामत के पिरामिड से परहेज कर रहा है, जैसा कि दूसरों ने उल्लेख किया है - बहुत सारे कष्टप्रद if letबयान एक दूसरे के अंदर और आगे दाहिनी ओर आगे बढ़ते हैं।

अन्य लाभ अक्सर तर्क है जिसे आप लागू करना चाहते हैं " if not let" की तुलना में अधिक " if let { } else" है।

यहां एक उदाहरण दिया गया है: मान लीजिए कि आप इसे लागू करना चाहते हैं accumulate- बीच में एक क्रॉस mapऔर reduceजहां यह आपको वापस चलने का एक सरणी देता है। यहाँ यह है guard:

extension Sliceable where SubSlice.Generator.Element == Generator.Element {

    func accumulate(combine: (Generator.Element,Generator.Element)->Generator.Element) -> [Generator.Element] {
        // if there are no elements, I just want to bail out and
        // return an empty array
        guard var running = self.first else { return [] }

        // running will now be an unwrapped non-optional
        var result = [running]

        // dropFirst is safe because the collection
        // must have at least one element at this point
        for x in dropFirst(self) {
            running = combine(running, x)
            result.append(running)
        }
        return result
    }

}


let a = [1,2,3].accumulate(+)  // [1,3,6]
let b = [Int]().accumulate(+)  // []

आप इसे बिना गार्ड के कैसे लिखेंगे , लेकिन फिर भी firstएक वैकल्पिक रिटर्न का उपयोग कर रहे हैं ? कुछ इस तरह:

extension Sliceable where SubSlice.Generator.Element == Generator.Element {

    func accumulate(combine: (Generator.Element,Generator.Element)->Generator.Element) -> [Generator.Element] {

        if var running = self.first  {
            var result = [running]

            for x in dropFirst(self) {
                running = combine(running, x)
                result.append(running)
            }
            return result
        }
        else {
            return []
        }
    }

}

अतिरिक्त घोंसला कष्टप्रद है, लेकिन यह भी, ifऔर elseअभी तक अलग होना तर्कसंगत नहीं है । खाली मामले के लिए जल्दी बाहर निकलना बहुत अधिक पठनीय है, और फिर बाकी फ़ंक्शन के साथ जारी रखें जैसे कि संभावना नहीं थी।


19

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

ध्यान दें कि गार्ड को अपने अन्य विवरण में रिटर्न या थ्रो की आवश्यकता होती है ।

गार्ड के साथ पार्सिंग JSON

नीचे एक उदाहरण है कि कोई व्यक्ति JSON ऑब्जेक्ट को पार्स करने के बजाय if-let का उपयोग कैसे कर सकता है। यह एक ब्लॉग प्रविष्टि का एक अंश है जिसमें एक खेल का मैदान फ़ाइल शामिल है जिसे आप यहाँ पा सकते हैं:

JSON को पार्स करने के लिए स्विफ्ट 2 में गार्ड का उपयोग कैसे करें

func parseJSONWithGuard(data : [String : AnyObject]) throws -> Developer {

    guard let firstname = data["First"] as? String  else {
        return Developer() // we could return a nil Developer()
    }

    guard let lastname = data["Last"] as? String else {
        throw ParseError.BadName // or we could throw a custom exception and handle the error
    }

    guard let website = data["WebSite"] as? String else {
        throw ParseError.BadName
    }

    guard let iosDev = data["iosDeveloper"] as? Bool else {
        throw ParseError.BadName
    }



    return Developer(first: firstname, last: lastname, site: website, ios: iosDev)

}

डाउनलोड खेल का मैदान: गार्ड खेल का मैदान

और जानकारी:

यहां द स्विफ्ट प्रोग्रामिंग लैंग्वेज गाइड का एक अंश दिया गया है :

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

यदि वह शर्त पूरी नहीं होती है, तो दूसरी शाखा के अंदर कोड निष्पादित किया जाता है। उस शाखा को उस कोड ब्लॉक से बाहर निकलने के लिए नियंत्रण स्थानांतरित करना होगा जो कि गार्ड स्टेटमेंट में दिखाई देता है। यह कंट्रोल ट्रांसफर स्टेटमेंट जैसे कि रिटर्न, ब्रेक या जारी रखने के साथ कर सकता है, या यह एक फ़ंक्शन या विधि को कॉल कर सकता है जो वापस नहीं आती है, जैसे fatalError () के रूप में।


7

एक लाभ बहुत सारे नेस्टेड if letस्टेटमेंट्स को खत्म कर देता है । 15:30 के आसपास WWDC "व्हाट्स न्यू इन स्विफ्ट" वीडियो देखें, "पिरामिड ऑफ़ डूम" शीर्षक वाला सेक्शन।


6

गार्ड का उपयोग कब करें

यदि आपको कुछ UITextField तत्वों या किसी अन्य प्रकार के उपयोगकर्ता इनपुट के साथ एक दृश्य नियंत्रक मिला है, तो आप तुरंत ध्यान देंगे कि आपको पाठ के अंदर आने के लिए textField.text वैकल्पिक को अनचेक करना होगा (यदि कोई हो!)। isEmpty आप यहाँ किसी भी अच्छा नहीं होगा, किसी भी इनपुट के बिना पाठ क्षेत्र बस शून्य वापस आ जाएगी।

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

func submit() {
    guard let name = nameField.text else {
        show("No name to submit")
        return
    }

    guard let address = addressField.text else {
        show("No address to submit")
        return
    }

    guard let phone = phoneField.text else {
        show("No phone to submit")
        return
    }

    sendToServer(name, address: address, phone: phone)
}

func sendToServer(name: String, address: String, phone: String) {
  ...
}

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

// चिंताओ का विभाजन

बिना गार्ड के

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

func nonguardSubmit() {
    if let name = nameField.text {
        if let address = addressField.text {
            if let phone = phoneField.text {
                sendToServer(name, address: address, phone: phone)
            } else {
                show("no phone to submit")
            }
        } else {
            show("no address to submit")
        }
    } else {
        show("no name to submit")
    }
}

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

https://thatthinginswift.com/guard-statement-swift/


5

गार्ड का उपयोग करने के साथ हमारी इंटेंसिटी स्पष्ट है। हम उस विशेष स्थिति से संतुष्ट नहीं होने पर बाकी कोड निष्पादित नहीं करना चाहते हैं। यहां हम श्रृंखला का विस्तार करने में सक्षम हैं, कृपया नीचे दिए गए कोड पर एक नज़र डालें:

guard let value1 = number1, let value2 = number2 else { return }
 // do stuff here

5

गार्ड बयान करने जा रहा है। यह अलग है

1) यह मुझे अनुमति देने के लिए नेस्टेड को कम करने की अनुमति देता है यदि कथन
2) यह मेरा दायरा बढ़ाता है जो मेरे चर सुलभ है

यदि कथन

func doTatal(num1 : Int?, num2: Int?) {
  // nested if statement
    if let fistNum = num1 where num1 > 0 {
        if let lastNum = num2 where num2 < 50 {

          let total = fistNum + lastNum
        }
    }
 // don't allow me to access out of the scope 
 //total = fistNum + lastNum 
}

गार्ड का बयान

func doTatal(num1 : Int?, num2: Int?) {
   //reduce  nested if statement and check positive way not negative way 
    guard let fistNum = num1 where num1 > 0 else{
      return
    }
    guard  let lastNum = num2 where num2 < 50 else {
     return
    }
    // increase my scope which my variable accessible
    let total = fistNum + lastNum

}

3

Apple प्रलेखन से:

गार्ड स्टेटमेंट

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

Synatx:

guard condition else {
    statements
}

फायदा:

1. guardकथन का उपयोग करके हम गहरी नेस्टेड स्थिति से छुटकारा पा सकते हैं जिसका एकमात्र उद्देश्य आवश्यकताओं के एक समूह को सत्यापित करना है।

2. यह विशेष रूप से एक विधि या कार्य को जल्दी से बाहर निकालने के लिए डिज़ाइन किया गया था।

यदि आप नीचे दिए गए कोड का उपयोग करते हैं तो यह कैसा दिखता है।

  let task = URLSession.shared.dataTask(with: request) { (data, response, error) in

        if error == nil {
            if let  statusCode = (response as? HTTPURLResponse)?.statusCode, statusCode >= 200 && statusCode <= 299 {
                if let data = data {

                    //Process Data Here.
                    print("Data: \(data)")

                } else {
                    print("No data was returned by the request!")
                }
            } else {
                print("Your request returned a status code other than 2XX!")
            }
        } else {
            print("Error Info: \(error.debugDescription)")
        }
    }
    task.resume()

यदि आप एक या अधिक शर्तों को पूरा नहीं कर रहे हैं तो गार्ड के उपयोग से आप नियंत्रण को एक दायरे से बाहर स्थानांतरित कर सकते हैं।

let task = URLSession.shared.dataTask(with: request) { (data, response, error) in

            /* GUARD: was there an error? */
            guard (error == nil) else {
                print("There was an error with your request: \(error)")
                return
            }

            /* GUARD: Did we get a successful 2XX response? */
            guard let statusCode = (response as? HTTPURLResponse)?.statusCode, statusCode >= 200 && statusCode <= 299 else {
                print("Your request returned a status code other than 2XX!")
                return
            }

            /* GUARD: was there any data returned? */
            guard let data = data else {
                print("No data was returned by the request!")
                return
            }

            //Process Data Here.
            print("Data: \(data)")
}
task.resume()

संदर्भ:

1. स्विफ्ट 2: गार्ड के साथ जल्दी बाहर निकलें 2. उधम 3. गार्ड स्टेटमेंट


लेकिन अगर आप बयानों के साथ उत्तरार्द्ध कर सकते हैं? if condition { return }असभ्य?
ओलिवर डिक्सन

2

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

देखें: http://ericcerney.com/swift-guard-statement/


1

यह वास्तव में कई दृश्य और वैकल्पिक के साथ एक अनुक्रम के प्रवाह को बहुत अधिक संक्षिप्त और स्पष्ट करता है और अगर बहुत से घोंसले के शिकार को कम करता है। इरा की जगह एरिका सदुन पोस्ट देखें । .... दूर किया जा सकता है, नीचे एक उदाहरण:

    let filteredLinks = locationsLinkedToList.filter({$0.actionVerb == movementCommand})
    guard let foundLink = filteredLinks.first else {return ("<Person> cannot go in that direction.", nil, nil)}
    guard filteredLinks.count == 1 else {return ("<Person> cannot decide which route to take.", nil, nil)}
    guard let nextLocation = foundLink.toLocation else {return ("<Person> cannot go in that direction.", nil, nil)}

देखें कि क्या चिपक गया।


1

सीधे शब्दों में कहें, यह निष्पादन से पहले खेतों को मान्य करने का एक तरीका प्रदान करता है। यह एक अच्छी प्रोग्रामिंग शैली है क्योंकि यह पठनीयता को बढ़ाता है। अन्य भाषाओं में, यह इस तरह दिख सकता है:

func doSomething() {
    if something == nil {
        // return, break, throw error, etc.
    }
    ...
}

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


1

स्रोत: स्विफ्ट में गार्ड

आइए इसे स्पष्ट रूप से समझने के लिए उदाहरण देखें

उदाहरण 1:

func validate() {         
    guard 3>2 else {             
    print ("False")             
    return         
    }         
    print ("True") //True     
} 
validate()

उपर्युक्त उदाहरण में हम देखते हैं कि 3 2 से अधिक है और गार्ड के अंदर का विवरण क्लॉज को छोड़ दिया जाता है और ट्रू प्रिंट किया जाता है।

उदाहरण 2:

func validate() {         
    guard 1>2 else {             
    print ("False")            //False 
    return         
    }         
    print ("True")      
} 
validate()

उपर्युक्त उदाहरण में हम देखते हैं कि 1 2 से छोटा है और गार्ड के अंदर दिए गए स्टेटमेंट को क्लॉज निष्पादित किया जाता है और फाल्स को रिटर्न के बाद प्रिंट किया जाता है।

Example 3: gaurd let, unwrapping optionals through guard let

func getName(args myName: String?) {
     guard let name = myName, !name.isEmpty else {
     print ("Condition is false")          // Condition is false            return         
     }         
     print("Condition is met\(name)")     
} 
getName(args: "")

उपरोक्त उदाहरण में हम गार्ड का उपयोग कर रहे हैं वैकल्पिक को खोलना। फ़ंक्शन getName में हमने टाइप स्ट्रिंग myName का एक वैरिएबल परिभाषित किया है जो वैकल्पिक है। हम तब गार्ड का उपयोग करते हैं यह जाँचने के लिए कि चर myName शून्य है या नहीं, यदि नाम और दोबारा जाँचने के लिए असाइन नहीं किया गया है, तो नाम खाली नहीं है। यदि दोनों स्थितियाँ योग्य हैं या सत्य हैं तो अन्य ब्लॉक को छोड़ दिया जाएगा और "शर्तों को नाम के साथ पूरा किया जाएगा" प्रिंट करें।

मूल रूप से हम यहां दो चीजों को अल्पविराम से अलग करके देख रहे हैं, पहला अलिखित और वैकल्पिक और यह जांचना कि क्या यह स्थिति को संतुष्ट करता है या नहीं।

यहाँ हम फंक्शन यानी खाली स्ट्रिंग के लिए कुछ भी नहीं कर रहे हैं और इसलिए हालत झूठी है प्रिंट है।

func getName(args myName: String?) {
     guard let name = myName, !name.isEmpty else {
     print ("Condition is false")          
     return         
     }        
     print("Condition is met \(name)") // Condition is met Hello    
} getName(args: "Hello")

यहाँ हम फंक्शन में "हेलो" पास कर रहे हैं और आप देख सकते हैं कि आउटपुट प्रिंट हुआ है "कंडीशन हेलो मिले"।

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