Computer >> कंप्यूटर ट्यूटोरियल >  >> स्मार्टफोन्स >> iPhone

Swift API कॉल्स आसान: एक शुरुआती गाइड

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

तीसरा बिंदु वही है जिसे हम इस लेख में कवर करेंगे। Swift 4 में Codable की शुरुआत के बाद से, API कॉल करना बहुत आसान हो गया है। पहले ज्यादातर लोग Alamofire और SwiftyJson जैसे पॉड्स का उपयोग करते थे (आप यहां पढ़ सकते हैं कि यह कैसे करना है)। अब Swift का तरीका बॉक्स से बाहर बहुत बेहतर है, इसलिए पॉड डाउनलोड करने का कोई कारण नहीं है।

आइए कुछ बिल्डिंग ब्लॉक्स के माध्यम से चलते हैं जो अक्सर API कॉल करने के लिए उपयोग किए जाते हैं। हम पहले इन कॉन्सेप्ट को कवर करेंगे, क्योंकि वे API कॉल कैसे करना है यह समझने के लिए महत्वपूर्ण भाग हैं।

  • Completion handlers
  • URLSession
  • DispatchQueue
  • Retain cycles

अंत में हम इसे सब एक साथ रखेंगे। मैं इस प्रोजेक्ट को बनाने के लिए ओपन सोर्स Star Wars API का उपयोग करूंगा। आप GitHub पर मेरा पूरा प्रोजेक्ट कोड देख सकते हैं।

डिस्क्लेमर अलर्ट: मैं कोडिंग में नया हूं और काफी हद तक सेल्फ-टॉट हूं। यदि मैं कुछ कॉन्सेप्ट को गलत तरीके से प्रस्तुत करता हूं तो क्षमा करें।

Completion handlers

फ्रेंड्स का वह एपिसोड याद है जहां फीबे ग्राहक सेवा से बात करने के लिए दिनों तक फोन से चिपकी रहती है? कल्पना करें कि उस फोन कॉल की शुरुआत में, पिप नाम का एक प्यारा व्यक्ति कहता: "कॉल करने के लिए धन्यवाद। मुझे नहीं पता कि आपको होल्ड पर कितने समय तक इंतजार करना पड़ेगा, लेकिन जब हम आपके लिए तैयार होंगे तो मैं आपको वापस कॉल करूंगा।" यह उतना मजेदार नहीं होता, लेकिन पिप फीबे के लिए एक completion handler की पेशकश कर रहा है।

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

यही API कॉल के साथ होता है। आप एक सर्वर को URL रिक्वेस्ट भेजते हैं, उससे कुछ डेटा मांगते हैं। आप आशा करते हैं कि सर्वर डेटा जल्दी वापस करेगा, लेकिन आप नहीं जानते कि इसमें कितना समय लगेगा। अपने यूज़र को सर्वर द्वारा डेटा देने के लिए धैर्यपूर्वक इंतजार कराने के बजाय, आप एक completion handler का उपयोग करते हैं। इसका मतलब है कि आप अपने ऐप को अन्य काम करने के लिए कह सकते हैं, जैसे पेज के बाकी हिस्से को लोड करना।

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

यहां एक उदाहरण है कि completion handler कैसा दिखता है। पहला उदाहरण API कॉल को ही सेट अप कर रहा है:

func fetchFilms(completionHandler: @escaping ([Film]) -> Void) {
    // lotsOfFilms वेरिएबल सेट अप करें
    var lotsOfFilms: [Film]
    // कुछ कोड के साथ API को कॉल करें
    // API से डेटा का उपयोग करके, lotsOfFilms को एक वैल्यू असाइन करें
    // completion handler को वेरिएबल, lotsOfFilms दें
    completionHandler(lotsOfFilms)
}
एक फंक्शन जो completion handler का उपयोग करता है

अब हम fetchFilms फंक्शन को कॉल करना चाहते हैं। कुछ बातें ध्यान देने योग्य हैं:

  • फंक्शन को कॉल करते समय आपको completionHandler को रेफरेंस करने की आवश्यकता नहीं है। केवल समय जब आप completionHandler को रेफरेंस करते हैं वह फंक्शन डिक्लेरेशन के अंदर होता है।
  • completion handler हमें उपयोग करने के लिए कुछ डेटा वापस देगा। हमारे द्वारा ऊपर लिखे गए फंक्शन के आधार पर, हम जानते हैं कि [Film] टाइप का डेटा प्राप्त करने की उम्मीद है। हमें डेटा को नाम देने की आवश्यकता है ताकि हम इसे संदर्भित कर सकें। नीचे मैं films नाम का उपयोग कर रहा हूं, लेकिन यह randomData, या कोई अन्य वेरिएबल नाम हो सकता है जो मुझे पसंद हो।

कोड कुछ इस तरह दिखेगा:

fetchFilms() { (films) in
    // completion handler द्वारा लौटाए गए डेटा के साथ कुछ करें
    print(films)
}
completion handler के साथ एक फंक्शन को लागू करना

URLSession

URLSession एक टीम के मैनेजर की तरह है। मैनेजर अपने दम पर कुछ नहीं करता। उसका काम अपनी टीम के लोगों के साथ काम साझा करना है, और वे काम पूरा करेंगे। उसकी टीम dataTasks हैं। हर बार जब आपको कुछ डेटा चाहिए, तो बॉस को लिखें और URLSession.shared.dataTask का उपयोग करें।

आप dataTask को अपने लक्ष्य को प्राप्त करने में मदद करने के लिए विभिन्न प्रकार की जानकारी दे सकते हैं। dataTask को जानकारी देना इनिशियलाइज़ेशन कहलाता है। मैं अपने dataTasks को URLs के साथ इनिशियलाइज़ करता हूं। dataTasks उनके इनिशियलाइज़ेशन के हिस्से के रूप में completion handlers का भी उपयोग करते हैं। यहां एक उदाहरण है:

let url = URL(string: "https://www.swapi.co/api/films")
let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
    // आपका कोड यहां
})
task.resume()
कुछ डेटा लाने के लिए URLSession का उपयोग कैसे करें

dataTasks completion handlers का उपयोग करते हैं, और वे हमेशा उसी प्रकार की जानकारी लौटाते हैं: data, response और error। आप इन डेटा टाइप को अलग-अलग नाम दे सकते हैं, जैसे (data, res, err) या (someData, someResponse, someError)। कन्वेंशन के लिए, कुछ स्पष्ट के साथ रहना सबसे अच्छा है बजाय नए वेरिएबल नामों के साथ दुष्ट होने के।

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

नीचे मैं एरर को वास्तव में सरलता से कंसोल पर एक एरर प्रिंट करके और फंक्शन से बाहर निकलकर हैंडल कर रहा हूं। यदि आप चाहें तो एरर को हैंडल करने के कई अन्य तरीके हैं। सोचें कि यह डेटा आपके ऐप के लिए कितना मौलिक है। उदाहरण के लिए, यदि आपके पास एक बैंकिंग ऐप है और यह API कॉल यूज़र्स को उनका बैलेंस दिखाता है, तो आप एरर को यूज़र को एक मॉडल प्रस्तुत करके हैंडल करना चाह सकते हैं जो कहता है, "क्षमा करें, हम अभी एक समस्या का सामना कर रहे हैं। कृपया बाद में पुनः प्रयास करें।"

if let error = error {
    print("Error accessing swapi.co: \(error)")
    return
}
एरर को हैंडल करें

अब हम रिस्पांस को देखते हैं। आप रिस्पांस को httpResponse में कास्ट कर सकते हैं। इस तरह आप स्टेटस कोड देख सकते हैं और कोड के आधार पर कुछ निर्णय ले सकते हैं। उदाहरण के लिए, यदि स्टेटस कोड 404 है, तो आप जानते हैं कि पेज नहीं मिला।

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

guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
    print("Error with the response, unexpected status code: \(response)")
    return
}

अंत में आप डेटा को ही हैंडल करते हैं। ध्यान दें कि हमने error या response के लिए completion handler का उपयोग नहीं किया है। ऐसा इसलिए है क्योंकि completion handler API से डेटा की प्रतीक्षा कर रहा है। यदि यह कोड के डेटा भाग तक नहीं पहुंचता है, तो हैंडलर को इनवोक करने की कोई आवश्यकता नहीं है।

डेटा के लिए, हम JSONDecoder का उपयोग डेटा को अच्छे तरीके से पार्स करने के लिए कर रहे हैं। यह काफी निफ्टी है, लेकिन इसके लिए आवश्यक है कि आपने एक मॉडल स्थापित किया हो। हमारा मॉडल FilmSummary कहलाता है। यदि JSONDecoder आपके लिए नया है, तो ऑनलाइन देखें कि इसका उपयोग कैसे करें और Codable का उपयोग कैसे करें। यह Swift 4 और उससे ऊपर में Swift 3 के दिनों की तुलना में वास्तव में सरल है।

नीचे दिए गए कोड में, हम पहले जांच रहे हैं कि डेटा मौजूद है। हम काफी निश्चित हैं कि यह मौजूद होना चाहिए, क्योंकि कोई एरर नहीं हैं और कोई अजीब HTTP रिस्पांस नहीं हैं। दूसरा, हम जांचते हैं कि क्या हम प्राप्त डेटा को उस तरीके से पार्स कर सकते हैं जिसकी हम उम्मीद करते हैं। यदि हम कर सकते हैं, तो हम फिल्म सारांश को completion handler को वापस करते हैं। बस अगर API से वापस करने के लिए कोई डेटा नहीं है, तो हमारे पास खाली ऐरे की एक फॉलबैक योजना है।

if let data = data, let filmSummary = try? JSONDecoder().decode(FilmSummary.self, from: data) {
    completionHandler(filmSummary.results ?? [])
}

तो API कॉल के लिए पूरा कोड इस तरह दिखता है:

func fetchFilms(completionHandler: @escaping ([Film]) -> Void) {
    let url = URL(string: domainUrlString + "films/")!
    let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
        if let error = error {
            print("Error with fetching films: \(error)")
            return
        }
        guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
            print("Error with the response, unexpected status code: \(response)")
            return
        }
        if let data = data, let filmSummary = try? JSONDecoder().decode(FilmSummary.self, from: data) {
            completionHandler(filmSummary.results ?? [])
        }
    })
    task.resume()
}

Retain cycles

नोट: मैं रिटेन साइकिल को समझने में बेहद नया हूं! यहां वह सार है जो मैंने ऑनलाइन शोध किया।

रिटेन साइकिल मेमोरी मैनेजमेंट के लिए समझना महत्वपूर्ण हैं। मूल रूप से आप चाहते हैं कि आपका ऐप उन मेमोरी बिट्स को साफ करे जिनकी उसे अब आवश्यकता नहीं है। मैं मानता हूं कि यह ऐप को अधिक प्रदर्शनशील बनाता है।

Swift आपकी मदद करने के लिए इसे स्वचालित रूप से करने के कई तरीके हैं। हालांकि कई तरीके हैं जिनसे आप गलती से अपने ऐप में रिटेन साइकिल कोड कर सकते हैं। एक रिटेन साइकिल का मतलब है कि आपका ऐप हमेशा कोड के एक निश्चित टुकड़े के लिए मेमोरी को पकड़ कर रखेगा। आमतौर पर यह तब होता है जब आपके पास दो चीजें होती हैं जिनके पास एक-दूसरे के लिए मजबूत पॉइंटर्स होते हैं।

इससे बचने के लिए, लोग अक्सर weak का उपयोग करते हैं। जब कोड का एक पक्ष weak होता है, तो आपके पास रिटेन साइकिल नहीं होता और आपका ऐप मेमोरी को रिलीज करने में सक्षम होगा।

हमारे उद्देश्य के लिए, एक सामान्य पैटर्न API को कॉल करते समय [weak self] का उपयोग करना है। यह सुनिश्चित करता है कि एक बार completion handler कुछ कोड लौटाता है, तो ऐप मेमोरी को रिलीज कर सकता है।

fetchFilms { [weak self] (films) in
    // कोड यहां
}

DispatchQueue

Xcode कोड को समानांतर में निष्पादित करने के लिए विभिन्न थ्रेड्स का उपयोग करता है। कई थ्रेड्स का लाभ यह है कि आप अगली चीज़ पर जाने से पहले एक चीज़ के खत्म होने का इंतजार नहीं करते। उम्मीद है कि आप यहां completion handlers के लिंक देखना शुरू कर सकते हैं।

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

टेबल व्यू UI का हिस्सा हैं, और सभी UI मैनिपुलेशन मेन डिस्पैच क्यू में किए जाने चाहिए। इसका मतलब है कि आपकी व्यू कंट्रोलर फाइल में कहीं, आमतौर पर viewDidLoad फंक्शन के हिस्से के रूप में, आपके पास कोड का एक बिट होना चाहिए जो आपके टेबल व्यू को रिफ्रेश करने के लिए कहता है।

हम केवल टेबल व्यू को रिफ्रेश करना चाहते हैं जब उसके पास API से कुछ नया डेटा हो। इसका मतलब है कि हम एक completion handler का उपयोग करेंगे जो हमें कंधे पर थपथपाए और हमें बताए कि वह API कॉल कब समाप्त हुआ। हम उस थपथपाहट की प्रतीक्षा करेंगे इससे पहले कि हम टेबल को रिफ्रेश करें।

कोड कुछ इस तरह दिखेगा:

fetchFilms { [weak self] (films) in
    self.films = films
    // मेन डिस्पैच क्यू का उपयोग करके टेबल व्यू को रीलोड करें
    DispatchQueue.main.async {
        tableView.reloadData()
    }
}

viewDidLoad vs viewDidAppear

अंत में आपको यह तय करने की आवश्यकता है कि अपने fetchfilms फंक्शन को कहां कॉल करना है। यह एक व्यू कंट्रोलर के अंदर होगा जो API से डेटा का उपयोग करेगा। दो स्पष्ट स्थान हैं जहां आप यह API कॉल कर सकते हैं। एक viewDidLoad के अंदर है और दूसरा viewDidAppear के अंदर है।

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

यदि आप उम्मीद करते हैं कि यूज़र के उस व्यू पर नेविगेट करने के बीच के समय में आपका डेटा बदल जाएगा, तो आप अपना API कॉल viewDidAppear में रखना चाह सकते हैं। हालांकि मुझे लगता है कि लगभग सभी ऐप्स के लिए, viewDidLoad पर्याप्त है। एप्पल सभी API कॉल के लिए viewDidAppear की सिफारिश करता है, लेकिन यह ओवरकिल लगता है। मुझे लगता है कि यह आपके ऐप को कम प्रदर्शनशील बना देगा क्योंकि यह कई अधिक API कॉल कर रहा है जितनी उसे आवश्यकता है।

सभी चरणों को संयोजित करना

पहला: वह फंक्शन लिखें जो API को कॉल करता है। ऊपर, यह fetchFilms है। इसमें एक completion handler होगा, जो उस डेटा को लौटाएगा जिसमें आप रुचि रखते हैं। मेरे उदाहरण में, completion handler फिल्मों की एक ऐरे लौटाता है।

दूसरा: इस फंक्शन को अपने व्यू कंट्रोलर में कॉल करें। आप इसे यहां करते हैं क्योंकि आप API से डेटा के आधार पर व्यू को अपडेट करना चाहते हैं। मेरे उदाहरण में, मैं API द्वारा डेटा लौटाए जाने के बाद एक टेबल व्यू को रिफ्रेश कर रहा हूं।

तीसरा: तय करें कि आप अपने व्यू कंट्रोलर में फंक्शन को कहां कॉल करना चाहेंगे। मेरे उदाहरण में, मैं इसे viewDidLoad में कॉल करता हूं।

चौथा: तय करें कि API से डेटा के साथ क्या करना है। मेरे उदाहरण में, मैं एक टेबल व्यू को रिफ्रेश कर रहा हूं।

NetworkManager.swift के अंदर (यह फंक्शन आपके व्यू कंट्रोलर में परिभाषित किया जा सकता है यदि आप चाहें, लेकिन मैं MVVM पैटर्न का उपयोग कर रहा हूं)।

func fetchFilms(completionHandler: @escaping ([Film]) -> Void) {
    let url = URL(string: domainUrlString + "films/")!
    let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
        if let error = error {
            print("Error with fetching films: \(error)")
            return
        }
        guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
            print("Error with the response, unexpected status code: \(response)")
            return
        }
        if let data = data, let filmSummary = try? JSONDecoder().decode(FilmSummary.self, from: data) {
            completionHandler(filmSummary.results ?? [])
        }
    })
    task.resume()
}

FilmsViewController.swift के अंदर:

final class FilmsViewController: UIViewController {
    private var films: [Film]?
    override func viewDidLoad() {
        super.viewDidLoad()
        NetworkManager().fetchFilms { [weak self] (films) in
            self?.films = films
            DispatchQueue.main.async {
                self?.tableView.reloadData()
            }
        }
    }
    // व्यू कंट्रोलर के लिए अन्य कोड
}

वाह, हमने कर दिखाया! मेरे साथ बने रहने के लिए धन्यवाद।

  1. एक्सेल डेटा टेबल मास्टर करें: 5 सरल, प्रभावी तरीके एक्सेल डेटा टेबल मास्टर करें: 5 सरल, प्रभावी तरीके

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

  1. मैक पर डिलीट की गई फ़ाइलों को वास्तव में अपरिवर्तनीय बनाएं: एक सुरक्षित इरेज़ गाइड मैक पर डिलीट की गई फ़ाइलों को वास्तव में अपरिवर्तनीय बनाएं: एक सुरक्षित इरेज़ गाइड

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

  1. बैकअप डेटा का मूल्य अनलॉक करें: एक सिद्ध रणनीति बैकअप डेटा का मूल्य अनलॉक करें: एक सिद्ध रणनीति

    डेटा बैकअप व्यक्तिगत और पेशेवर दोनों के लिए समान रूप से आवश्यक है। हम सभी डेटा का क्लाउड, एक्सटर्नल ड्राइव्स, और SD कार्ड पर बैकअप लेते हैं। हम में से कुछ को अपना डेटा स्टोर करने के लिए दूसरों की तुलना में बहुत अधिक स्पेस की आवश्यकता हो सकती है। हम अक्सर पाते हैं कि हम डिवाइस पर एक ही फ़ाइल की कई प्