GraphQL iOS: Swift Uygulamasında Bulut Fonksiyonlarını Kullanma
Bu makalede, Back4app’te NodeJS Cloud Code ile GraphQL’i nasıl kullanacağınızı gösterdim.
Bu rehberde ise Apollo GraphQL iOS İstemcisini Swift ile nasıl kullanacağınızı gösterdim.
Şimdi hepsini bir araya getirelim ve gerçekten kolay kod üreterek birçok karmaşık işlemi yapalım. Ayrıca XCode’un Class’ları değiştirdiğimizde bile bizim için otomatik olarak herhangi bir API kodu oluşturmasını sağlayalım.
Kulağa hoş geliyor mu? Öyleyse biraz kahve alın ve devam edin!
Contents
- 1 Başlamadan önce…
- 2 Bize yardımcı olacak birkaç yazılım parçası…
- 3 Sınıflarımızı Oluşturmak
- 4 Bulut Kodunu getirin, bebeğim!
- 5 Test… Test…
- 6 Biraz XCoding
- 7 GraphQL dosyamız
- 8 Bazı Swift Kodları
- 9 Hadi çalıştıralım!
- 10 Sonuç
- 11 Swift uygulamasında bulut fonksiyonlarını kullanmak için hangi yazılım kullanılabilir?
- 12 NPM’nin büyüsü nedir?
Başlamadan önce…
Bir Uygulama oluşturulmuş bir Back4app hesabına ihtiyacınız olacak. Henüz bir hesabınız yoksa, bu kılavuzu izleyin ve kısa sürede her şeye sahip olacaksınız.
Bize yardımcı olacak birkaç yazılım parçası…
Ayrıca işleri hızlandırmak için birkaç şey kullanacağız.
Elbette, isterseniz hepsini manuel olarak da yapabilirsiniz, ancak özellikle yeni başlayanlar için bu yolu önermiyorum.
Paketleri manuel olarak eklediğinizde, bir süre sonra zahmetli olabilecek paketlerin bakımını da manuel olarak yapmanız gerekecektir.
Burada göstereceğim paket yöneticilerini kullanmak zorunda değilsiniz, ancak manuel yönetim yapmak yerine en azından bazı paket yöneticilerini kullanmanızı şiddetle tavsiye ederim. Daha önce de söylediğim gibi, manuel yönetim zamanla tuhaflaşabilir.
Ben iOS paket yönetimi için Cocoapods ‘u ve masaüstü yönetimi için NPM ‘i kullanacağım, ancak yine de size hangisi uygunsa onu kullanmaktan çekinmeyin.
Cocoapods kurulumu için talimatları bu sitede bulabilirsiniz.
NPM kurulumu için talimatlar bu sitede bulunabilir.
Sınıflarımızı Oluşturmak
Üç sınıf uygulayacağız: Sahip, Köpek ve Cins.
Modelimiz şunu ima edecektir:
- Bir Sahip birden fazla Köpeğe sahip olabilir
- Bir Köpeğin sadece bir Cinsi olabilir
Mülklerimiz olacak:
- Sahibi
- isim (String)
- Yaş (Sayı)
- adres (String)
- hasDogs (Bir Sahibin birden fazla Köpeği olabileceği için Köpek ile ilişki)
- Köpek
- isim (String)
- doğum günü (Tarih)
- Cins (Bir Köpeğin yalnızca bir Cinsi olduğu için Cins’e İşaretçi)
- Cins
- İsim (String
Bu sınıfları grafiksel veya programlı olarak oluşturun ve bazı verilerle doldurun. Sınıflarım bu şekilde sonuçlandı:
Cins
Köpek
Sahibi
Bulut Kodunu getirin, bebeğim!
Biraz Bulut Kodu zamanı. Ama bu sefer bu konuda da daha derinlere inmek istiyorum.
Cloud Code’un NPM modülleriyle uyumlu olduğunu daha önce söylemiş miydim? Evet uyumlu! Ve size ÇOK zaman kazandırabilir!
Sahip olmak istediğiniz ama başkasının çoktan yaptığı o harika işlevselliği biliyor musunuz? Eğer bu bir NPM modülü ise, kullanabilirsiniz!
Bu öğreticiyi kullanarak modüllerin nasıl kullanılacağı hakkında zaten bir makale var, bu yüzden bu uygulama için Moment ‘i kullanacağım, böylece bir Köpeğin doğum gününü kullanabilir ve ay cinsinden yaşını hesaplayabiliriz.
Böylece package.json dosyam şöyle görünecek:
{ "bağımlılıklar": { "an": "*" } }
Bu * işareti en son sürümü kullanacağım anlamına geliyor.
Bulut Kodum aşağıdaki gibi oldu. İyi yorumlanmış olduğundan burada fazla ayrıntıya girmeyeceğim, ancak ilk satırda Moment NPM modülünü kullandığımı görebilirsiniz:
// Moment NPM Modülünü Instantiating const moment = require('moment') Parse.Cloud.define("retrieveOwnersOrderedByAgeDescending", async req => { /* Bu fonksiyon, yaşa göre azalan şekilde sıralanmış tüm Sahipleri getirir. Sahip yoksa, boş bir dizi alınır. */ const sorgu = new Parse.Query("Sahip"); query.descending("yaş") const sonuçlar = await sorgu.find(); sonuçları döndür; }); Parse.Cloud.define("retrieveAllGermanShepherds", async req => { /* Bu fonksiyon "Alman Çoban Köpeği" cinsine sahip Köpekleri getirir Köpeklerin tüm özellikleri alınır. Eğer Dogs yoksa, boş bir dizi alınır. */ const breedQuery = new Parse.Query("Cins"); breedQuery.equalTo("name", "German Shepherd") const query = new Parse.Query("Dog"); query.matchesQuery("breed", breedQuery); const sonuçlar = await query.find(); return results; }); Parse.Cloud.define("retrieveDogIncludingBreedByName", async req => { /* Bu fonksiyon, Köpek ismine göre ırk detayları (isim) dahil olmak üzere belirli Köpek detaylarını alır Dogs ve Breed'in tüm özellikleri alınır. Köpek yoksa null değeri alınır. */ const query = new Parse.Query("Dog"); query.equalTo("name", req.params.name); query.include("cins") const sonuçlar = await sorgu.find(); return results; }); Parse.Cloud.define("retrieveDogsNamesWithAgesInMonths", async req => { /* Bu işlev, NPM modülünü kullanarak doğum günü özelliği Ay'a dönüştürülmüş Dogs adlarını alır. Köpeklerin sadece isimleri alınır ve yaşları ay olarak hesaplanır. Eğer Dogs yoksa, boş bir dizi alınır. */ let köpekler = []; const query = new Parse.Query("Dog"); const sonuçlar = await sorgu.find(); for (let i = 0; i < results.length; i ++){ // NPM Modülü Moment kullanılarak Ay cinsinden yaşın hesaplanması ageInMonths = moment.duration(moment().diff(results[i].get("birthday")).humanize(); yeniKöpek = { "dogName": results[i].get("name"), "dogAgeInMonths": ageInMonths } dogs.push(newDog); } köpekleri döndür; });
Dört yöntemimi açığa çıkaran schema.graphql dosyam şu şekilde ortaya çıktı:
extend type Sorgu { getAllOwnersAgeDescending: [OwnerClass!]! @resolve(to: "retrieveOwnersOrderedByAgeDescending") getAllGermanShepherds: [DogClass!]! @resolve(to: "retrieveAllGermanShepherds") getThisDogWithBreed (name:String): [DogClass!]! @resolve(to: "retrieveDogIncludingBreedByName") getDogsAgesInMonths: [DogAge!]! @resolve(to: "retrieveDogsNamesWithAgesInMonths") } type DogAge { dogName: String! dogAgeInMonths: String! }
Sözdizimini anlamadıysanız, “Küçük bir ekstra adım” bölümündeki bu makaleye göz atın.
getDogsAgesInMonths üzerindeki [DogAge!]! ifadesine dikkat edin. Sistem tarafından oluşturulan bir nesneyi alacağım için GraphQL’in yorumlayabileceği bir şeması olmayacak, bu nedenle istemcimizin yorumlayabilmesi için türü de oluşturmam gerekiyor.
Test… Test…
Biraz test zamanı!
Parse GraphQL Konsolumuza gidelim ve sorgularımızı çalıştırıp sonuçlarını kontrol edelim:
getAllOwnersAgeDescending için sorgu:
query{ getAllOwnersAgeDescending { isim yaş adres } }
getAllGermanShepherds için sorgu:
sorgu { getAllGermanShepherds { isim doğum günü } }
getThisDogWithBreed için sorgu:
query{ getThisDogWithBreed(name: "Fido"){ isim doğum günü cins{ isim } } }
getDogsAgesInMonths için sorgu:
query{ getDogsAgesInMonths }
Her şey çalışıyor! Harika! Şimdi sıra…
Biraz XCoding
Back4app’ten ihtiyacımız olan her şeyi aldık ve çalıştırıyoruz. Şimdi bunu XCode üzerinde kullanma zamanı.
Bu kılavuzda bunu nasıl yapacağımızı göstermiştik ama bu sefer biraz daha ileri gittik: birden fazla metodumuz var, bunlardan biri değişkenleri bekliyor, bu yüzden birkaç değişiklik yapmamız gerekecek.
Bu makaleyi henüz takip etmediyseniz, çok ayrıntılı olduğu için takip etmenizi şiddetle tavsiye ederim.
Makalede anlatıldığı gibi uygulamayı oluşturarak ve Apollo istemcisini yükleyerek başlayalım.
Daha sonra Main.storyboard dosyanızı açın, sağ üst köşedeki Objects butonuna tıklayın ve View Controller’a bir Table View sürükleyip bırakın:
Köşeleri sürükleyerek Tablo Görünümünüzün boyutunu Görünüm Denetleyicisinin tüm Görünümüyle eşleşecek şekilde değiştirin:
Ve ekranın sağ alt köşesindeki Yeni Kısıtlamalar Ekle düğmesine tıklayarak dört taraf için de Kısıtlamalar oluşturun. Dört kenara (kırmızı işaretler) tıklayın ve bu yeni kısıtlamaları atamak için Kısıtlama Ekle düğmesine tıklayın:
Şimdi, Tablo Görünümü seçiliyken (seçmek için üzerine tıklayın), bir Prototip Hücre ekleyelim. Sağ üstteki Öznitelik Denetçisine tıklayın ve Prototip Hücreler kutusundaki 0’ı 1 ile değiştirin:
Şimdi, yeni oluşturulan Prototip Hücreyi seçmek için üzerine tıklayın ve ona iyi bir tanımlayıcı verin: “hücre”.
Bunu daha sonra kodda bu hücreyi tanımlamak için kullanacağız.
Şimdi Veri Kaynağımızı ve Temsilcimizi Tablo Görünümünden Görünüm Denetleyicimize bağlamamız gerekiyor.
Klavyenizdeki Control tuşunu basılı tutarken, Tablo Görünümüne tıklayın ve onu Görünüm Denetleyicinizin üstündeki sarı simgeye sürükleyin, üzerine geldiğinizde Görünüm Denetleyicisi yazan simgeye.
Tablo Görünümü bağlantısını orada bıraktığınızda küçük bir açılır pencere gösterilecektir. Açılır pencerede hem DataSource hem de Delegate’i seçin:
Şimdi, bu temelleri kapsayacaktır, ancak verilerimizi Back4app’den aldıktan sonra bu Tablo Görünümünde bir yenileme çağırmamız gerekecek. Bunu yapmak için bir Outlet oluşturmalı ve onu Kullanıcı Arayüzümüze bağlamalıyız.
Bunu yapmanın en kolay yolu, ekranın sağ üst köşesindeki Yardımcı Düzenleyiciyi Göster seçeneğine tıklamaktır; böylece kullanıcı arayüzünü ve kodu yan yana görebilirsiniz.
Ardından Tablo Görünümünüze Control ile tıklayın ve koda sürükleyin:
Bıraktığınızda bir açılır pencere göreceksiniz. Bunun için İsim girin ve Bağlan’a tıklayın:
Bu işlem tamamlandığında, güzel bir Outlet’iniz bağlanmış olacaktır (satır numarasının üzerindeki küçük daireye dikkat edin), böylece artık bu Tablo Görünümü için kodu çağırabiliriz:
Tüm bunları yaptıktan sonra ViewController.swift dosyamıza gidebiliriz çünkü sıra geldi…
GraphQL dosyamız
GraphQLkılavuzumuz size GraphQL dosyanızı nasıl oluşturacağınızı gösterdi. Bu proje için benimki şu şekilde sonuçlandı:
sorgu findAllOwners{ getAllOwnersAgeDescending{ isim yaş adres } } sorgu findAllGermanShepherds{ getAllGermanShepherds { isim } } query findThisDog ($name: String!){ getThisDogWithBreed(name: $name){ isim doğum günü cins{ isim } } } sorgu ageInMonths{ getDogsAgesInMonths }
Bazı Swift Kodları
Bir kez daha, Apollo’yu Swift’te nasıl yapılandıracağımızıbu kılavuzda zaten ele almıştık, ancak bugünün kodunda birkaç değişiklik var.
Verileri Tablo Görünümümüzde grafiksel olarak görüntüleyeceğimiz için, Veri Kaynağımızın ve Delegemizin yürütmesi için iki yöntem eklemeliyiz. Bu yöntemler şunlardır
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
ve
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
Bunlar kodda belgelendiği için bu konuda fazla bilgi vermeyeceğim. Sadece bu iki yöntemin Tablo Görünümümüzün çalışması için zorunlu olduğunu unutmayın.
Tam kodunuz şu şekilde görünmelidir:
// // ViewController.swift // GraphQLApollo // // Venom tarafından 19/08/19 tarihinde oluşturulmuştur. // Telif Hakkı © 2019 Venom. Tüm hakları saklıdır. // import UIKit Apollo'yu içe aktar sınıf ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var tableView: UITableView! var liste = [] as [String] // Bu dizi, görüntülememiz için değerleri tutacaktır // Apollo İstemci başlatma. // Daha fazla bilgi için: https://www.back4app.com/docs/ios/swift-graphql apollo olsun: ApolloClient = { let configuration = URLSessionConfiguration.default configuration.httpAdditionalHeaders = [ "X-Parse-Application-Id": "lAcIOgR0ndd7R4uMqovhNAoudpi6tMsrOI9KCuyr", "X-Parse-Client-Key": "f1wwm6uWqQoxazys3QQrrtY4fKuQuxYvNYJmYQJP" ] url = URL(string: "https://parseapi.back4app.com/graphql") olsun! return ApolloClient( networkTransport: HTTPNetworkTransport( url: url, yapılandırma: yapılandırma ) ) }() override func viewDidLoad() { super.viewDidLoad() // Görünümü yükledikten sonra herhangi bir ek kurulum yapın. apollo.fetch(query: FindAllOwnersQuery()) { result in guard let data = try? result.get().data else { return } for name in data.getAllOwnersAgeDescending { //Liste dizimiz için her bir ismi ekler self.liste.append(isim.isim!) } //aşağıdaki satır, verileri aldıktan sonra Tablo Görünümümüzü yeniden yüklemeye zorlayacaktır DispatchQueue.main.async { self.tableView.reloadData() } } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // Bu Fonksiyon, Veri Kaynağı ve Delegate aracılığıyla Tablo Görünümümüz tarafından çağrılır. // Sadece Tablo Görünümünün göstereceği nesne sayısını döndürür. // Bir Tablo Görünümünün çalışması için zorunludur. return liste.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // Bu Fonksiyon Veri Kaynağı ve Delegate aracılığıyla Tablo Görünümümüz tarafından çağrılır. // Storyboard üzerinde belirlediğimiz Tanımlayıcı ile görüntülenecek Hücreleri oluşturur // Bir Tablo Görünümünün çalışması için zorunludur. let cell = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "cell") cell.textLabel?.text = liste[indexPath.row] return(hücre) } }
Hadi çalıştıralım!
Kodumuzu çalıştırma zamanı! Command + R tuşlarına basın ve her şey doğruysa, Tablo Görünümünüzde adlarımızı görmelisiniz:
Harika, değil mi?
Şimdi kodumuzu diğer GraphQL yöntemlerimizi çalıştıracak şekilde değiştirebilir ve nasıl çalışacağını görebiliriz!
getAllGermanShepherds yöntemimizi çalıştırmak için GraphQL sorgumuzu değiştirelim:
override func viewDidLoad() { super.viewDidLoad() // Görünümü yükledikten sonra herhangi bir ek kurulum yapın. apollo.fetch(query: FindAllGermanShepherdsQuery()) { result in guard let data = try? result.get().data else { return } print(data.getAllGermanShepherds) for name in data.getAllGermanShepherds { //Liste dizimiz için her bir ismi ekler self.liste.append(isim.isim!) } //aşağıdaki satır, verileri aldıktan sonra Tablo Görünümümüzü yeniden yüklemeye zorlayacaktır DispatchQueue.main.async { self.tableView.reloadData() } } }
ve sonuç…
Peki ya sorgumuza bir değişken aktarmak istersek?
override func viewDidLoad() { super.viewDidLoad() // Görünümü yükledikten sonra herhangi bir ek kurulum yapın. apollo.fetch(query: FindThisDogQuery(name: "Fido")) { result in guard let data = try? result.get().data else { return } print(data.getThisDogWithBreed) for name in data.getThisDogWithBreed { //Liste dizimiz için her bir ismi ekler self.list.append(isim.isim! + " - " + (isim.cins?.isim!)!) } //aşağıdaki satır, verileri aldıktan sonra Tablo Görünümümüzü yeniden yüklemeye zorlayacaktır DispatchQueue.main.async { self.tableView.reloadData() } } }
Ve şimdi Fido’nun bir Pug olduğunu biliyoruz:
Peki ya yeni bir tür döndüren metoda ne dersiniz? Bunu da test edelim:
override func viewDidLoad() { super.viewDidLoad() // Görünümü yükledikten sonra herhangi bir ek kurulum yapın. apollo.fetch(query: AgesInMonthsQuery()) { result in guard let data = try? result.get().data else { return } print(data.getDogsAgesInMonths) for dog in data.getDogsAgesInMonths { //Liste dizimiz için her bir ismi ekler self.list.append(dog.dogName + " - " + dog.dogAgeInMonths) } //aşağıdaki satır, verileri aldıktan sonra Tablo Görünümümüzü yeniden yüklemeye zorlayacaktır DispatchQueue.main.async { self.tableView.reloadData() } } }
ve sonuç:
Sonuç
Bulut kodu havalıdır. GraphQL süper havalı. Apollo, iOS yerel uygulamalarınıza yeni bir harikalık düzeyi getiriyor. Üçü bir araya geldiğinde, çok az çabayla çok karmaşık uygulamalar oluşturmak için ciddi bir güce sahip olursunuz.
Artık bir Uygulama için tamamen çalışan, oluşturulması ve zaman içinde bakımı kolay bir akış oluşturabildiğinize göre, asıl soru şu: Bundan sonra ne oluşturacaksınız?
Umarım bunu beğenmişsinizdir! Yakında daha fazlasını yayınlayacağız! Bizi izlemeye devam edin!
Swift uygulamasında bulut fonksiyonlarını kullanmak için hangi yazılım kullanılabilir?
Kendi seçiminize bağlı olacaktır. Kolayca kullanabileceğiniz ve çalıştırabileceğiniz yazılımı kullanmalısınız. Yukarıdaki pratikte aşağıdaki ikisini kullandım.
-IOS paket yönetimi için Cocoapods
-Masaüstü paket yönetimi için NPM
NPM’nin büyüsü nedir?
Bulut kodu NPM modülleriyle uyumludur. Bu harika bir şeydir. Yığınla zaman kazanmanıza yardımcı olacaktır. Ayrıca rakiplerinize karşı da avantaj sağlayacaktır. Yani, NPM’nin bulut kodlarıyla uyumluluğu size bir ivme kazandıracaktır.