Kloningan Instagram menggunakan SwiftUI dan GraphQL – Login
Dalam artikel kami sebelumnya tentang cara membuat aplikasi kloningan Instagram, Anda telah mempelajari cara mengonfigurasi segala sesuatunya agar SwiftUI aktif dan berjalan di XCode 11, dan membuat tampilan Sing Up yang berfungsi penuh dengan GraphQL.
Hari ini kita akan belajar cara membuat tampilan login dan membuat pengguna keluar.
Kita akan membutuhkan proyek dari postingan sebelumnya, jadi jika Anda tidak mengikuti postingan tersebut, saya sangat menyarankan Anda untuk mengikutinya.
Kencangkan sabuk pengaman Anda dan ayo kita mulai!
Untuk pembelajaran yang lebih baik, unduh proyek iOS Instagram Clone dengan kode sumber.
Contents
Apakah Anda ingin memulai dengan cepat?
Kloning Aplikasi ini dari Hub kami dan mulai gunakan tanpa kerepotan!
Membuat tampilan Login
Tampilan Login kita akan sangat mirip dengan tampilan SignUp kita, bahkan lebih sederhana.
Di dalam atau Mutasi Pengguna, kita hanya membutuhkan dua parameter: nama pengguna dan kata sandi:
Kueri dan mutasi akan bergantung pada versi Parse yang Anda pilih:
Parse 3.7.2:
mutation logInUser($username: String!, $password: String!){ pengguna{ logIn(nama pengguna: $nama pengguna, kata sandi: $kata sandi){ sessionToken } } }
Parse 3.8:
mutasi logInPengguna($username: String!, $password: String!){ logIn(username: $username, password: $password){ sessionToken } }
Parse 3.9:
mutasi logInPengguna($username: String!, $password: String!){ logIn(username: $username, password: $password){ sessionToken } }
sehingga kita hanya perlu menanyakan hal tersebut kepada pengguna kita.
Mari kita mulai dengan menambahkan SwiftUI View baru dengan masuk ke File > New > File dan pilih SwiftUI View kita
Mari beri nama tampilan ini LogInView.swift dan tambahkan buka di proyek kita:
Dan seperti yang telah Anda pelajari, buat VStack Anda dengan kontrol yang kita perlukan:
- TextField untuk nama pengguna
- SecureField untuk kata sandi
- Tombol untuk melakukan aksi
Untuk menjaga konsistensi desain, saya memindahkan warna yang akan kita gunakan ke AppDelegate.swift, jadi saya harus mengimpor SwiftUI di sana juga:
import SwiftUI let lightGreyColor = Color(red: 239.0/255.0, green: 243.0/255.0, blue: 244.0/255.0, opacity: 1.0) let lightBlueColor = Color(red: 36.0/255.0, green: 158.0/255.0, blue: 235.0/255.0, opacity: 1.0)
Jangan lupa untuk menghapus garis warna dari SignUpView.swift dan LogInView.swift.
Selain itu, untuk menjaga konsistensi kontrol, saya baru saja menyalin dan menempelkan dari tampilan SignUp dan menghapus TextField email dan mengubah TextField untuk mencerminkan fungsi baru. Kode saya berakhir seperti ini:
struct LogInView: View { @State var nama pengguna: String = "" @State var kata sandi: String = "" @State private var showingAlert = false var body: beberapa View { VStack { Text("Masuk") .font(.largeTitle) .foregroundColor (warna biru muda) .fontWeight(.semibold) .padding(.bottom, 20) TextField("Nama Pengguna", text: $nama_pengguna) .padding() .background(lightGreyColor) .cornerRadius(5.0) .padding(.bottom, 20) SecureField("Kata Sandi", text: $kata sandi) .padding() .background(lightGreyColor) .cornerRadius(5.0) .padding(.bottom, 20) Tombol (action: { }){ Text("Masuk!") .font(.headline) .foregroundColor(.white) .padding() .frame(width: 220, height: 60) .background(lightBlueColor) .cornerRadius(15.0) } } .padding() } }
Ini sangat sederhana. Mari kita lihat bagaimana tampilannya?
Ubah ContentView.swift Anda untuk menampilkan tampilan tersebut:
struct ContentView : View { var body: beberapa View { LogInView() } }
Terlihat rapi!
Mari kita buat lebih rapi dengan menambahkan logo kita di bagian atas!
Logo kita akan terdiri dari sebuah gambar yang akan kita integrasikan ke dalam proyek kita. Saya menggunakan gambar ini.
Seret dan letakkan gambar tersebut ke folder Assets.xcassets di dalam proyek:
Seharusnya akan terlihat seperti ini:
Mulai sekarang kita dapat mereferensikannya ke dalam kode kita dengan nama: logo-social.
Daftar sekarang ke Back4App dan mulailah membangun Aplikasi Klon Instagram Anda.
Logo Kami
Logo kita akan terdiri dari gambar tersebut, tetapi hanya dengan meletakkan gambar di sana akan terlihat amatir. Kami akan membuatnya bersinar: melingkar, dengan ukuran tetap, beberapa goresan di tepian dan, tentu saja, bayangan jatuh karena… bayangan jatuh.
Kode untuk semua itu terlihat seperti ini:
Image("logo-sosial") .resizable() .aspectRatio(contentMode: .fit) .frame(width: 150, height: 150) .clipShape(Circle()) .overlay(Circle().stroke(Color.blue, lineWidth: 2)) .shadow(radius: 5) .padding(.bottom, 75)
Dan itu berjalan di bagian atas VStack kita:
var body: some View { VStack{ Image("logo-sosial") .mengubah ukuran () .aspectRatio(contentMode: .fit) .frame(width: 150, height: 150) .clipShape(Circle()) .overlay(Circle().stroke(Color.blue, lineWidth: 2)) .shadow(radius: 5) .padding(.bottom, 75) Text("Masuk") .font(.largeTitle) .foregroundColor(lightBlueColor) .fontWeight(.semibold) .padding(.bottom, 20) ...
Sekarang, bukankah itu indah?
SessionToken
Proses login kita akan mengembalikan sebuah string sessionToken. Kita harus menjaga sessionToken tersebut tetap aman karena akan digunakan selama operasi kita: selama sessionToken tersebut valid, kita akan memiliki akses ke aplikasi kita. Ketika sessionToken dihapus atau tidak valid, panggilan kita akan ditolak.
Karena ini berhubungan langsung dengan keamanan, kita perlu menyimpannya dengan aman. Tempat yang tepat untuk melakukannya adalah Keychain di iOS.
Satu hal tentang Keychain adalah sulit dan membosankan untuk digunakan, jadi saya memutuskan untuk menggunakan pembungkus ini untuk mengelolanya. Ini membuat hidup jauh lebih mudah dan karena kita sudah menggunakan Cocoapods, ini sangat masuk akal.
Mari kita edit Podfile kita dan tambahkan ini ke pod kita:
pod 'SwiftKeychainWrapper'
lalu mari kita perbarui Pods kita dengan perintah
install pod
dan terakhir, buka kembali proyek xcworkspace kita.
Kita sekarang siap menggunakan mesin Keychain kita untuk…
Menyimpan sessionToken
Menurut dokumentasi pod baru kita, cara untuk menyimpan nilai ke keychain adalah
KeychainWrapper.standard.set("SomeValue", forKey: "SomeKey")
tetapi mari kita tambahkan beberapa logika ke dalamnya.
Untuk memulai, mari kita mengimpor pembungkus kita:
import SwiftKeychainWrapper
Hal pertama yang harus kita lakukan adalah memanggil mutasi logInUser kita dan ketika ia merespons, kita menyimpan sessionToken jika ada. Jika tidak, kita harus memberi tahu pengguna dengan sebuah peringatan.
Sekarang, jika Anda ingat pada artikel sebelumnya, kita sudah memiliki kode peringatan termasuk strukturnya. Mari kita gunakan kembali dengan menghapus kode di bawah ini dari SingUpView.swift kita dan mengopernya ke file AppDelegate.swift sehingga semua view dapat mengaksesnya:
struct Message { var alertTitle: String = "" var alertText: String = "" } var myMessage = Message()
Sekarang, kembali ke logika kita, hal pertama yang harus kita lakukan adalah menentukan apakah pengguna telah mengisi kotak teks nama pengguna dan kata sandi. Jika tidak, tidak ada informasi untuk proses login dan kita harus memberi tahu pengguna tentang hal itu.
Kode aksi kita untuk tombol login harus memeriksanya. Mari kita tambahkan potongan kode ini di sana untuk memeriksa ukuran string dari variabel state yang terhubung ke kolom teks tersebut:
Button(action: { // Memeriksa apakah ada kata sandi yang diketikkan if (self.password.count == 0 || self.username.count == 0){ // Jika tidak, kita harus menampilkan Peringatan myMessage.alertText = "Anda harus memberikan Nama Pengguna dan Kata Sandi." myMessage.alertTitle = "Ups..." self.showingAlert = true } else { // Jika sudah, kita bisa melanjutkan } }){ Text("Masuk!") .font(.headline) .foregroundColor(.white) .padding() .frame(width: 220, height: 60) .background(lightBlueColor) .cornerRadius(15.0) } .alert(isPresented: $showingAlert) { Peringatan (judul: Text(myMessage.alertTitle), pesan: Text(myMessage.alertText), dismissButton: .default(Text("OK"))) }
dan mengujinya…
Bagus!
Sekarang kita harus memanggil mutasi GraphQL kita untuk mengambil sessionToken dan, jika kita mendapatkannya, menyimpannya di Keychain.
Anda telah mempelajari cara memanggil mutasi, jadi mari kita lakukan, tetapi kali ini jika kita mendapatkan sessionToken, kita akan menyimpannya:
// Lakukan mutasi LogInUser, dengan mengoper parameter yang baru saja kita dapatkan dari TextFields kita apollo.perform(mutasi: LogInUserMutation(username: self.username, password: self.password)){ menghasilkan // Mari kita alihkan hasilnya agar kita dapat memisahkan hasil yang berhasil dengan yang gagal switch hasil { // Dalam kasus sukses case .success(let graphQLResult): // Kami mencoba untuk mem-parse hasil kami if let sessionToken = graphQLResult.data?.users?.logIn.sessionToken { myMessage.alertTitle = "Yay!" myMessage.alertText = "Pengguna sudah masuk!" self.showingAlert = true print ("User sessionToken " + sessionToken) // Tuliskan sessionToken ke Keychain kita let _: Bool = KeychainWrapper.standard.set(sessionToken, forKey: "Back4Gram.sessionToken") } // tetapi jika terjadi kesalahan GraphQL, kami menampilkan pesan tersebut else if let errors = graphQLResult.errors { // Kesalahan GraphQL myMessage.alertTitle = "Ups!" myMessage.alertText = "Kami mendapatkan kesalahan GraphQL: " + errors.description self.showingAlert = true print(errors) } // Jika terjadi kegagalan, kita menampilkan pesan tersebut case .failure(let error): // Kesalahan jaringan atau format respons myMessage.alertTitle = "Ups!" myMessage.alertText = "Kami mengalami kesalahan: " + error.localizedDescription self.showingAlert = true print(error) } }
Mari kita coba!
Bagus! Tapi bagaimana kita tahu bahwa itu benar-benar berhasil?
Kita dapat pergi ke Dasbor Parse Aplikasi kita dan memeriksa apakah ada objek Session baru yang ditulis:
Seperti pesona!
Dan karena kita sudah sampai di sini…
Bagaimana jika kita menambahkan tombol untuk keluar? Hanya untuk pengujian agar kita tahu semuanya berjalan lancar:
Button(action: { // Periksa apakah ada sessionToken storeString yang seharusnya hanya keluar jika login. if (KeychainWrapper.standard.string(forKey: "Back4Gram.sessionToken") != nil) { print("SessionToken ditemukan! Kita bisa logout.") // Lakukan mutasi LogOutUser apollo.perform(mutasi: LogOutUserMutation()){ menghasilkan // Mari kita alihkan hasilnya agar kita dapat memisahkan yang berhasil dari yang gagal switch hasil { // Dalam kasus sukses case .success(let graphQLResult): // Kita mencoba untuk mem-parse hasil kita if let hasil = graphQLResult.data?.users?.logOut { if (hasil) { myMessage.alertTitle = "Yay!" myMessage.alertText = "Pengguna keluar!" self.showingAlert = true // Menghapus sessionToken yang tersimpan let _: Bool = KeychainWrapper.standard.set("", forKey: "Back4Gram.sessionToken") } else { myMessage.alertTitle = "Ups!" myMessage.alertText = "Operasi logout pengguna dikembalikan dengan hasil False." self.showingAlert = true } } // tetapi jika terjadi kesalahan GraphQL, kami menampilkan pesan tersebut else if let errors = graphQLResult.errors { // Kesalahan GraphQL myMessage.alertTitle = "Ups!" myMessage.alertText = "Kami mendapatkan kesalahan GraphQL: " + errors.description self.showingAlert = true print(errors) } // Jika terjadi kegagalan, kita menampilkan pesan tersebut case .failure(let error): // Kesalahan jaringan atau format respons myMessage.alertTitle = "Ups!" myMessage.alertText = "Kami mengalami kesalahan: " + error.localizedDescription self.showingAlert = true print(error) } } } else { // Kesalahan jaringan atau format respons myMessage.alertTitle = "Ups!" myMessage.alertText = "Pengguna sepertinya tidak masuk." self.showingAlert = true } }){ Text("Log Out") .font(.headline) .foregroundColor(.white) .padding() .frame(width: 220, height: 60) .background(lightBlueColor) .cornerRadius(15.0) } .alert(isPresented: $showingAlert) { Peringatan (judul: Text(myMessage.alertTitle), pesan: Text(myMessage.alertText), dismissButton: .default(Text("OK"))) }
Sekali lagi, mari kita coba!
Bagus!
Kita akan memindahkan tombol Log Out ke tempat lain nanti, tetapi untuk saat ini, tombol tersebut berfungsi untuk menunjukkan bahwa alur kita bekerja.
Tapi bagaimana dengan objek Session kita sekarang setelah kita logout?
Secara otomatis hilang, seperti yang diharapkan!
Kesimpulan
Selamat! Anda sekarang sudah mengimplementasikan fungsi login dan logout! Tidak hanya itu, Anda juga telah mempelajari cara memanggil mutasi yang berbeda, memvalidasi hasil, dan menyimpan nilai dalam Keychain! Betapa mengagumkannya hal itu!
Di bab selanjutnya, kita akan mulai bekerja dengan beberapa tampilan dan mulai membangun tampilan utama kita!
Nantikan terus!
Referensi
- Bagian 1 dari seri ini adalah Instagram Clone menggunakan Swift UI dan GraphQL.
- Bagian 2 adalah Login Instagram Menggunakan Swift UI dan GraphQL.
- Bagian 3 adalah Tampilan Profil Menggunakan Swift UI dan GraphQL.
- Bagian 4 adalah Tampilan Beranda Kloningan Instagram.
- Unduh proyek Instagram Clone iOS dengan kode sumber dan mulailah menggunakan Back4App.
Daftar sekarang ke Back4App dan mulai buat Aplikasi Instagram Clone Anda.
Apa itu SwiftUI?
SwiftUI adalah cara baru untuk membuat antarmuka pengguna bagi aplikasi di platform Apple. SwiftUI memungkinkan pengembang menentukan UI menggunakan kode Swift.
Apa itu sessionToken?
Proses login yang sedang kita kembangkan akan mengembalikan string sessionToken. String tersebut perlu diamankan. Jika kita dapat menjaga sessionToken tetap valid, kita akan memiliki akses ke aplikasi, jika tidak, kita akan kehilangan akses ke aplikasi. Hal ini terkait dengan keamanan.
Apa itu Keychain?
Kita tahu bahwa sessionToken terkait dengan keamanan aplikasi Anda. Jadi, sessionToken perlu disimpan di tempat yang aman. Tempat aman itu disebut keychain. SessionToken mungkin agak sulit digunakan dan mungkin juga terasa membosankan.