Interaksi dengan server melalui API di iOS pada Swift 3. Bagian 2

Artikel ini adalah kelanjutan dari artikel Berinteraksi dengan server melalui API di iOS pada Swift 3. Bagian 1 dan memperbarui artikel lama yang ditulis dalam Objective-C pada swift 3.

Teori singkat


DAPATKAN permintaan


GET adalah metode permintaan HTTP paling sederhana, dan itulah yang digunakan browser untuk memuat halaman web. Ini digunakan untuk meminta konten yang terletak di URL tertentu. Konten tersebut mungkin, misalnya, halaman web, gambar, atau file audio. Secara konvensi, permintaan GET bersifat hanya-baca dan, sesuai dengan standar W3C, tidak boleh digunakan dalam operasi yang mengubah sisi server. Misalnya, kami tidak akan menggunakan permintaan GET untuk mengirim formulir atau mengirim foto, karena operasi ini memerlukan beberapa perubahan di sisi server (kami akan menggunakan POST dalam kasus ini).

Permintaan POST


POST mengirim data untuk diproses lebih lanjut ke URL. Parameter dimasukkan dalam badan permintaan menggunakan format yang sama dengan GET. Misalnya, jika kami ingin memposting formulir yang berisi dua bidang, nama dan usia, maka kami akan mengirim sesuatu yang mirip dengan nama = Martin & umur = 29 di badan permintaan.

Metode pengiriman parameter ini banyak digunakan di halaman web. Kasus yang paling populer adalah formulir. Ketika kami mengisi formulir di situs dan klik Kirim, kemungkinan besar permintaan akan POST.

Dalam aplikasi kami, kami menggunakan POST untuk membuat peringkat lelucon. Kami akan mengirimkan suara (atau +1, atau -1) ke server jarak jauh.

Data permintaan POST dapat disusun menggunakan berbagai format. Parameter biasanya diformat sesuai dengan standar pengkodean form-url (sesuai dengan standar HTML W3C). Ini adalah format default dan banyak digunakan di banyak browser. Metode kami menerima kamus Kamus sebagai argumen, tetapi kami tidak dapat mengirim kamus Kamus melalui koneksi HTTP karena ini adalah tipe Swift internal. Untuk meneruskan koneksi HTTP, kita perlu membuat representasi kamus yang dapat dikenali. Ini seperti berkomunikasi dengan orang asing. Kami menerjemahkan pesan kami ke dalam bahasa universal, dan itu menerjemahkan dari bahasa universal ke dalam bahasa aslinya. Bahasa universal dalam HTTP adalah standar W3C, bahasa kami Swift, bahasa penerima tidak diketahui oleh kami.

Standar W3C mendefinisikan aturan yang mendefinisikan apa arti representasi yang dapat dikenali untuk setiap kasus. Dalam kasus kami, kami perlu menyajikan parameter mengikuti bagian form-url-encoded dari standar (misalnya, param1 = var1 & param2 = var2).

Tampilan web


Menggunakan alat bahasa pemrograman, kami dapat mengirim permintaan ke server jauh. Inilah yang dilakukan browser sebelum menampilkan halaman web. Perbedaannya hanya pada konten jawabannya. Halaman web diformat menggunakan standar HTML, yang mendefinisikan seperangkat aturan tentang cara mendefinisikan berbagai tag markup secara grafis. Aturan-aturan ini tampak sederhana, tetapi menampilkan seluruh halaman mengikuti standar W3C adalah tugas yang sulit. Untungnya, iOS memiliki komponen UIWebView built-in yang menggunakan mesin WebKit yang terkenal dan menafsirkan HTML / CSS / JavaScript dan menampilkan seluruh halaman web di dalam UIView.

Ada beberapa kasus di mana kami ingin mengontrol aliran navigasi. Misalnya, kami ingin tahu kapan konten tertentu atau URL tertentu dimuat.

Atau mungkin kami menerapkan browser yang aman untuk anak-anak, kami ingin memblokir pengguna dari memuat halaman yang masuk dalam kriteria tertentu, seperti seks atau narkoba. Untuk semua jenis penyesuaian seperti itu, kami membuat instance kelas yang mengimplementasikan protokol UIWebViewDelegate sebagai delegasi UIWebView. Kami dapat menerapkan metode berikut:

webView:shouldStartLoadWithRequest:navigationType: webViewDidStartLoad: webViewDidFinishLoad: webView:didFailLoadWithError: 

Dengan menggunakan metode pertama, kita dapat mengontrol aliran navigasi dengan mengizinkan atau memblokir permintaan tertentu. Tiga metode lainnya adalah peristiwa informasi (nama metode memberi ide bagus tentang peristiwa itu).

Implementasi pemungutan suara melalui permintaan POST


Kami akan menambahkan file MainViewController.swift dan HTTPCommunication.swift , dan membuat file WebViewController.swift baru di mana kami mendefinisikan webView kami.

Pertama, buat file WebViewController.swift baru dan tentukan kelas WebViewController di dalamnya:

WebViewController.swift

 import UIKit class WebViewController: UIViewController { } extension WebViewController { } 

Sekarang kami mengimplementasikan fungsionalitas untuk membuat permintaan POST di kelas yang bertanggung jawab untuk semua operasi HTTP kami: kelas komunikasi HTTPC. Untuk melakukan ini, tambahkan metode postURL (_: params: completionHandler :) baru di HTTPCommunication.swift, yang mirip dengan metode recoverveURL (_: completionHandler :) sebelumnya.

HTTPCommunication.swift

 class HTTPCommunication: NSObject { … func retrieveURL(_ url: URL, completionHandler: @escaping ((Data) -> Void)) { … } // TODO:    } // end of class HTTPCommunication 

Kode metode

 func postURL(_ url: URL, params: [String: Int], completionHandler: @escaping ((Data) -> Void)) { // (K.1) self.completionHandler = completionHandler // (K.2) func postBody(params: [String: Int]) -> Data? { // (K.3) var paramsArr: [String] = [] for (key, value) in params { paramsArr.append("\(key)=\(value)") } let postBodyString: String = paramsArr.joined(separator: "&") let postBodyData: Data? = postBodyString.data(using: .utf8) return postBodyData } var request: URLRequest = URLRequest(url: url) // (K.4) request.httpMethod = "POST" request.httpBody = postBody(params: params) let session: URLSession = URLSession(configuration: .default, delegate: self, delegateQueue: nil) // (K.5) let task: URLSessionDownloadTask = session.downloadTask(with: request) task.resume() } 

(K.1) Dengan penutupan, kami akan bekerja di luar fungsi ini, oleh karena itu kami menyatakannya dengan @escaping.
(K.2) Kami menyimpan penutupan yang disahkan di properti Handler penyelesaian.
(K.3) Kami menulis metode yang mengubah kamus parameter yang dikirimkan ke dalam bentuk string, dan kemudian menyandikan string ini ke dalam tipe data dalam pengkodean utf8.
(K.4) Kami membuat permintaan dengan url yang dikirimkan dan mengkonfigurasinya: mengatur POST sebagai metode, dan menjadikan parameter tipe data kami dengan utf8 sebagai badan permintaan.
(K.5) Akhirnya, buat sesi dengan konfigurasi default dan delegasi seperti diri kita sendiri. Dan kami membuat tugas untuk memuat hasil permintaan ini ke penyimpanan sementara. Pada akhirnya, defrost tugas.

Sekarang mari kita tambahkan antarmuka yang diperlukan ke MainViewController.swift. Tambahkan dua tombol untuk memilih voteUp dan voteDown, yang masing-masing akan menambah atau mengurangi peringkat dari lelucon saat ini. Kami juga menambahkan Tombol "Chuck Who?", Yang akan kami isi dengan fungsionalitas di bagian pada tampilan web.

Di MainViewController.swift, masukkan kode inisialisasi voteUpButton, voteDownButton dan chuckWhoButton.

MainViewController.swift

 lazy var jokeLabel: UILabel! = … var jokeID: Int! lazy var activityView: UIActivityIndicatorView! = … //TODO:    lazy var stackView: UIStackView! = … 

Kode Inisialisasi Tombol
 lazy var voteUpButton: UIButton! = { // (L.1) let button: UIButton = UIButton(type: .system) // (L.2) button.setTitle("Vote Up", for: .normal) button.sizeToFit() button.addTarget(self, action: #selector(self.voteUp), for: .touchUpInside) // (L.3) self.view.addSubview(button) // (L.4) return button // (L.5) }() lazy var voteDownButton: UIButton! = { let button: UIButton = UIButton(type: .system) button.setTitle("Vote Down", for: .normal) button.sizeToFit() button.addTarget(self, action: #selector(self.voteDown), for: .touchUpInside) self.view.addSubview(button) return button }() lazy var chuckWhoButton: UIButton! = { let button: UIButton = UIButton(type: .system) button.setTitle("Chuck Who?", for: .normal) button.sizeToFit() button.addTarget(self, action: #selector(self.chuckWho), for: .touchUpInside) self.view.addSubview(button) return button }() 

Kode inisialisasi untuk ketiga tombol adalah sama.

(L.1) Kami mendeklarasikan variabel malas dan menginisialisasi dengan penutupan.
(L.2) Di dalam penutupan, kami mendefinisikan variabel lokal untuk tombol, tipe sistem, tentukan nama dan ukuran.
(L.3) Kami mengaitkan dengan tombol tindakan yang sesuai ketika ditekan.
(L.4) Tambahkan ke hierarki tampilan.
(L.5) Dan kami menetapkan variabel lokal ini ke variabel malas kami.

Selanjutnya, di MainViewController.swift, masukkan kode metode untuk tombol

MainViewController.swift

 class MainViewController: UIViewController { … func retrieveRandomJokes() { … } // TODO:    } // end of class MainViewController 

Kode metode untuk tombol
 func voteUp() { let http: HTTPCommunication = HTTPCommunication() // (M.1) let params: [String: Int] = ["joke_id": self.jokeID, "vote": 1] // (M.2) if let url = URL(string: "http://example.com/rater/vote") { // (M.3) http.postURL(url, params: params) { (data) in // (M.4) print("\(data). Voted Up") } } } func voteDown() { let http: HTTPCommunication = HTTPCommunication() let params: [String: Int] = ["joke_id": self.jokeID, "vote": -1] if let url = URL(string: "http://example.com/rater/vote") { http.postURL(url, params: params) { (data) in print("\(data). Voted Down") } } } func chuckWho() { } 

Kode metode untuk memilih naik dan turun adalah sama.

(M.1) Buat objek kelas untuk komunikasi dengan server.
(M.2) Kami membuat kamus parameter yang menyertakan id lelucon yang kami pilih, dan nilai sebenarnya dari pemungutan suara adalah +1 atau -1.
(M.3) Selanjutnya, kami mendapatkan url dengan aman dari bilah alamat dari domain pelatihan kami http://example.com/rater/vote.
(M.4) Dan kami mengirimkan melalui POST permintaan untuk url parameter kami. Dan cetak ke konsol garis yang menunjukkan penyelesaian permintaan.

Selanjutnya, di MainViewController.swift kita menulis ulang kode metode configStackView, dengan mempertimbangkan perubahan yang dilakukan pada UI.

MainViewController.swift

 func configStackView() -> UIStackView { let innerStackView: UIStackView = UIStackView(arrangedSubviews: [self.voteUpButton, self.voteDownButton]) // (N.1) innerStackView.axis = .horizontal // (N.2) innerStackView.distribution = .fillEqually let mainStackView: UIStackView = UIStackView(arrangedSubviews: [self.jokeLabel, innerStackView, self.chuckWhoButton]) // (N.3) mainStackView.spacing = 50 // (N.4) mainStackView.axis = .vertical mainStackView.distribution = .fillEqually self.view.addSubview(mainStackView) // (N.5) return mainStackView } 

(N.1) Buat innerStackView yang berisi dua tombol untuk pemungutan suara.
(N.2) Kami mengekspos sumbu vertikal; distribusinya sama.
(N.3) Di mainStackView utama, tambahkan innerStackView dan tombol tentang Chuck Norris ke label dari bagian terakhir.
(N.4) Konfigurasikan mainStackView.
(N.5) Tambahkan mainStackView ke hierarki tampilan.

Kami meluncurkan aplikasi kami dan melihat antarmuka seperti pada Gambar. 1


Gambar. 1 Antarmuka aplikasi kami dengan tombol yang ditambahkan untuk pemungutan suara

kami memverifikasi bahwa ketika memberikan suara untuk atau melawan lelucon, pesan-pesan berikut ini ditampilkan di konsol:

345 bytes. Voted Up

atau

345 bytes. Voted Down

yang menunjukkan permintaan POST yang berhasil diselesaikan ke server.

Kami menulis aplikasi lelucon menggunakan icndb API dan GET HTTP verb. Kami dapat menunjukkan lelucon ini pada UIView dan setiap lelucon dapat dihargai. Tindakan ini mengirim permintaan POST ke server jarak jauh, yang seharusnya menghemat estimasi kami.

Menggunakan webViews untuk menampilkan halaman web


Kami akan menambahkan webView untuk menampilkan halaman wikipedia tentang Chuck Norris. Dia bingung dengan satu sentuhan tombol.

Dalam file WebViewController.swift, tuliskan fungsi rintisan fungsi berikut:

WebViewController.swift

 import UIKit class WebViewController: UIViewController { lazy var webView: UIWebView = { // (O.1) self.configWebView() }() lazy var toolbar: UIToolbar = { // (O.2) self.configToolbar() }() override func viewDidLoad() { super.viewDidLoad() } func back() { // (O.3) self.webView.goBack() } func forward() { self.webView.goForward() } } extension WebViewController { func configWebView() -> UIWebView { // (O.4) } func configToolbar() -> UIToolbar { // (O.5) } func configConstraints() { // (O.6) } } 

(O.1) Kami membuat variabel malas untuk webView
(O.2) dan bilah alat.
(O.3) Kami membuat metode maju dan mundur, untuk navigasi pada riwayat kunjungan tautan.
(O.4) Kami menambahkan metode inisialisasi webView ke ekstensi
(O.5) dan toolBar
(O.6) dan kendala untuk antarmuka.

Sekarang kita lukis kode masing-masing fungsi:

 func configWebView() -> UIWebView { let webView: UIWebView = UIWebView() // (P.1) self.view.addSubview(webView) return webView } 

(P.1) Kami menginisialisasi webView dan menambahkan tampilan ke hierarki.

 func configToolbar() -> UIToolbar { let toolbar: UIToolbar = UIToolbar(frame: CGRect.zero) // (Q.1) let backButton: UIBarButtonItem = UIBarButtonItem(title: "<", style: .plain, target: self, action: #selector(self.back)) // (Q.2) let forwardButton: UIBarButtonItem = UIBarButtonItem(title: ">", style: .plain, target: self, action: #selector(self.forward)) toolbar.setItems([backButton, forwardButton], animated: false) // (Q.3) toolbar.backgroundColor = UIColor.lightGray // (Q.4) self.view.addSubview(toolbar) return toolbar } 

(R.1) Buat bilah alat dengan bingkai nol.
(R.2) Kami membuat dua tombol untuk menavigasi riwayat tautan kunjungan. Dengan nama "<" dan ">" dan tindakan dilampirkan ke metode yang sesuai di webView.
(Q.3) Tambahkan tombol-tombol ini ke toolbar.
(R.4) Atur warna latar belakang, seperti Bilah navigasi, abu-abu muda. Dan tambahkan tampilan ke hierarki.

 func configConstraints() { self.webView.translatesAutoresizingMaskIntoConstraints = false // (R.1) NSLayoutConstraint.activate([ // (R.2) self.webView.topAnchor.constraint(equalTo: self.topLayoutGuide.topAnchor), self.webView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), self.webView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), self.webView.bottomAnchor.constraint(equalTo: self.toolbar.topAnchor) ]) self.toolbar.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ // (R.3) self.toolbar.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), self.toolbar.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), self.toolbar.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), self.toolbar.heightAnchor.constraint(equalToConstant: 44.0) ]) } 

(R.1) Nonaktifkan masker autoresisasi sehingga tidak bertentangan dengan kendala kami
(R.2) Untuk webView, konfigurasikan keempat sisi tampilan.
(R.3) Untuk bilah alat, konfigurasikan tiga sisi tampilan, kecuali untuk bagian atas, tetapi tambahan atur ketinggian ke ukuran standar 44.0.

Dan tulis ulang kode ViewDidLoad () sebagai berikut:

 override func viewDidLoad() { super.viewDidLoad() self.configConstraints() // (S.1) if let url = URL(string: "http://en.wikipedia.org/wiki/Chuck_Norris") { // (S.2) let request: URLRequest = URLRequest(url: url) // (S.3) self.webView.loadRequest(request) // (S.4) } } 

(S.1) Meminta pengaturan kendala.
(S.2) Dapatkan url dengan aman dari bilah alamat di halaman Wikipedia en.wikipedia.org/wiki/Chuck_Norris
(S.3) Kami membuat permintaan dari url.
(S.4) Dan kami menjalankan permintaan yang diberikan di webView.

Kami kembali ke MainViewController dan mengisinya dengan metode memanggil informasi tentang Chuck Norris.

MainViewController.swift

 func chuckWho() { self.navigationController?.show(WebViewController(), sender: self) // (T.1) } 

(T.1) Saat Anda mengklik tombol ini pada tumpukan navigationController, masukkan instance webView baru.

Fig. 2 menunjukkan bagaimana tampilan webView dalam aplikasi kita.


Fig. 2. Tampilan akhir dari webView yang telah kami terapkan

Source: https://habr.com/ru/post/id415615/


All Articles