[Xamarin iOS] Consuming REST API
January 1, 2017 Leave a comment
Setelah memahami cara mengkonsumsi REST API dengan Xamarin android pada tautan berikut, sekarang kita akan mencoba penerapan pada aplikasi iOS dengan Xamarin.
Buatlah sebuah aplikasi iOS pada Xamarin. Design main.storyboard anda seperti berikut :
Main.storyboard di atas terdiri dari :
- UINavigationController
- MainController : terhubung langsung dengan UINavigationController. MainController terdiri dari sebuah UITableView (kita beri nama “TabelFood”) dan sebuah UITextField (diberi nama “txtTitle”). UITableView secara otomatis memiliki sebuah UITableViewCell, atur style-nya menjadi “Right Detail” dan berilah identifier-nya “CellData”.
- FormController : Controller ini digunakan untuk melakukan proses edit data (insert, update dan delete). FormController terdiri dari dua buah UITextField guna input data baru yaitu txtName dan txtPrice.
- Sebuah segue dari UINavigationController ke MainController dengan type segue “root”
- Sebuah segue dari MainController ke FormController dengan type “show” dan nama segue “editSegue”
Setelah selesai melakukan pengaturan UI pada masing-masing controller buatlah class FoodMenu.cs sebagai model dari data Food. Masukkan code berikut :
using System;
namespace silexiOS
{
public class FoodMenu
{
private int id;
private string name;
private double price;
public FoodMenu(string name, double price)
{
this.name = name;
this.price = price;
}
public FoodMenu(int id, string name, double price)
{
this.id = id;
this.name = name;
this.price = price;
}
public int Id { get { return this.id; } }
public string Name { get { return this.name; } }
public double Price { get { return this.price; } }
}
}
Tambahkan package “Newtonsoft.Json” pada project anda untuk memudahkan mengkonsumsi json format yang didapat dari REST API. Buatlah sebuah fungsi “FoodLoader.cs” untuk mengakses REST API dari server, masukkan code berikut :
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using Newtonsoft.Json.Linq;
namespace silexiOS
{
public class FoodLoader
{
private static readonly string serverLink = "http://localhost/medical/web/index2.php/";
public FoodLoader()
{ }
public static List<FoodMenu> LoadData()
{
string link = serverLink + "daftar";
List<FoodMenu> datas = new List<FoodMenu>();
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(link);
request.Method = "GET";
request.ContentType = "application/json";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream receiveStream = response.GetResponseStream();
StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
string outputString = readStream.ReadToEnd();
response.Close();
readStream.Close();
outputString = outputString.Trim().Replace("// ", "");
var resultArray = JArray.Parse(outputString);
for (int i = 0; i < resultArray.Count; i++)
{
var jstock = (JObject)resultArray[i];
FoodMenu temp_data = new FoodMenu(
int.Parse((string)jstock["id"]),
(string)jstock["name"],
double.Parse((string)jstock["price"])
);
datas.Add(temp_data);
}
}
}
catch (Exception e)
{
throw;
}
return datas;
}
public static String InsertData(FoodMenu data)
{
string link = serverLink + "insert";
String result = "";
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(link);
StringBuilder postData = new StringBuilder();
postData.Append("name=" + data.Name + "&");
postData.Append("price=" + data.Price.ToString());
var data_encode = Encoding.ASCII.GetBytes(postData.ToString());
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data_encode.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data_encode, 0, data_encode.Length);
}
var response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream receiveStream = response.GetResponseStream();
StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
result = readStream.ReadToEnd();
response.Close();
readStream.Close();
}
}
catch (Exception)
{
throw;
}
return result;
}
public static String UpdateData(FoodMenu data, int id)
{
string link = serverLink + "update/" + id.ToString();
String result = "";
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(link);
StringBuilder postData = new StringBuilder();
postData.Append("name=" + data.Name + "&");
postData.Append("price=" + data.Price.ToString());
var data_encode = Encoding.ASCII.GetBytes(postData.ToString());
request.Method = "PUT";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data_encode.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data_encode, 0, data_encode.Length);
}
var response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream receiveStream = response.GetResponseStream();
StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
result = readStream.ReadToEnd();
response.Close();
readStream.Close();
}
}
catch (Exception)
{
throw;
}
return result;
}
public static String DeleteData(int id)
{
string link = serverLink + "delete/" + id.ToString();
String result = "";
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(link);
request.Method = "DELETE";
var response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream receiveStream = response.GetResponseStream();
StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
result = readStream.ReadToEnd();
response.Close();
readStream.Close();
}
}
catch (Exception)
{
throw;
}
return result;
}
}
}
Dua buah class di atas sama dengan class yang di definisikan pada aplikasi Android yang telah dibuat sebelumnya.
Buatlah class “FoodAdapter.cs” dimana class ini merupakan source yang digunakan untuk mengisi row data pada TabelFood yang ada pada MainController.
using System;
using System.Collections.Generic;
using UIKit;
using Foundation;
namespace silexiOS
{
public class FoodAdapter : UITableViewSource
{
private MainController parent;
private List<FoodMenu> datas = new List<FoodMenu>();
private string cellIdentifier = "CellData";
public FoodAdapter(MainController parent, List<FoodMenu> datas)
{
this.parent = parent;
this.datas = datas;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return this.datas.Count;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell(cellIdentifier);
if (cell == null)
{
cell = new UITableViewCell(UITableViewCellStyle.Default, cellIdentifier);
}
cell.TextLabel.Text = this.datas[indexPath.Row].Name;
cell.DetailTextLabel.Text = this.datas[indexPath.Row].Price.ToString();
return cell;
}
}
}
Sekarang kita akan mulai masuk mengelola code pada MainController dan FormController yang menjalankan proses utama dari aplikasi yang dibuat. Masukkan code berikut pada MainController :
using Foundation;
using System;
using System.Collections.Generic;
using UIKit;
namespace silexiOS
{
public partial class MainController : UIViewController
{
public int EditPosition = -1;
List<FoodMenu> datas = new List<FoodMenu>();
public MainController (IntPtr handle) : base (handle)
{
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
InitializeView();
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
this.InitializeBar();
}
private void InitializeBar()
{
List<UIBarButtonItem> rightButtons = new List<UIBarButtonItem>();
rightButtons.Add(new UIBarButtonItem(
UIBarButtonSystemItem.Add,
(sender, e) => { PerformSegue("editSegue", this); }
));
rightButtons.Add(new UIBarButtonItem(
UIBarButtonSystemItem.Refresh,
(sender, e) => { this.InitializeView(); }
));
NavigationItem.RightBarButtonItems = rightButtons.ToArray();
}
private void InitializeView()
{
this.EditPosition = -1;
txtTitle.Text = "Loading...";
this.datas = FoodLoader.LoadData();
TabelFood.Source = new FoodAdapter(this, this.datas);
TabelFood.ReloadData();
txtTitle.Text = "List Food";
}
public override void PrepareForSegue(UIStoryboardSegue segue, NSObject sender)
{
base.PrepareForSegue(segue, sender);
if (segue.Identifier == "editSegue")
{
var vc = segue.DestinationViewController as FormController;
}
}
}
}
Yang terjadi pada MainController adalah :
- Terdapat 2 variabel yang didefinisikan yaitu “EditPosition” dan “datas”. EditPosition digunakan untuk mengetahui posisi data yang di-klik oleh user (ingat kita akan membuat fungsi edit dan delete), sedangkan “datas” akan menyimpan data daftar makanan yang di dapatkan dari REST API.
- Jika nilai “EditPosition” lebih kecil dari 0 (nol) artinya tidak ada data yang dipilih oleh pengguna.
- Ketika screen akan muncul maka akan dijalankan fungsi ViewWillAppear dimana fungsi ini akan menjalankan fungsi “InitializeView()”
- Fungsi “InitializeView()” proses utama-nya adalah mengunduh data yang disediakan dengan REST dimana data yang diunduh langsung ditampilkan pada “TabelFood” yang ada pada screen.
- Selain menampilkan data ke dalam TabelFood, InitializeView() juga akan memberikan nilai pada “EditPosition” menjadi -1 (ketika kita memanggil/refresh data sudah pasti belum ada data yang dipilih) dan mengeset nilai txtTitle guna menampilkan indikator proses unduh data. Jika proses unduh sedang berjalan, maka txtTitle akan menampilkan tulisan “Loading…”.
- Setelah menjalankan ViewWillAppear, MainController menjalankan ViewDidLoad() ketika screen telah di load.
- ViewDidLoad akan menjalankan fungsi “InitializeBar()” dimana fungsi ini akan menambahkan dua buah bar menu pada screen yaitu menu “Add” dan menu “Refresh”.
- Ketika menu “Add” dipilih maka akan menjalankan fungsi untuk menjalankan segue dimana Controller segue yang dituju adalah form untuk menambahkan data baru. Sedangkan jika menu “Refresh” dipilih, aplikasi akan mengunduh ulang data pada server REST API dan menampilkan ulang data terbaru ke dalam tabel.
Setelah code dijalankan akan muncul screen MainController yang menampilkan data dari server REST API.
Sekarang mari kita membuat code yang akan mengeksekusi code FormController untuk menambah data baru. Masukkan code berikut pada FormController :
using Foundation;
using System;
using System.Collections.Generic;
using UIKit;
namespace silexiOS
{
public partial class FormController : UIViewController
{
private int EditId = 0;
private string EditName;
private double EditPrice;
public FormController (IntPtr handle) : base (handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
this.InitializeBar();
this.InitializeData();
}
private void InitializeBar()
{
List<UIBarButtonItem> rightButtons = new List<UIBarButtonItem>();
rightButtons.Add(new UIBarButtonItem(
UIBarButtonSystemItem.Save,
(sender, e) => {
FoodMenu temp = new FoodMenu(txtName.Text, double.Parse(txtPrice.Text));
if (this.EditId == 0)
FoodLoader.InsertData(temp);
else
FoodLoader.UpdateData(temp, EditId);
NavigationController.PopViewController(true);
}
));
if (this.EditId > 0)
{
rightButtons.Add(new UIBarButtonItem(
UIBarButtonSystemItem.Trash,
(sender, e) =>
{
FoodLoader.DeleteData(this.EditId);
NavigationController.PopViewController(true);
}
));
}
NavigationItem.RightBarButtonItems = rightButtons.ToArray();
}
private void InitializeData()
{
if (this.EditId > 0)
{
this.txtName.Text = EditName;
this.txtPrice.Text = EditPrice.ToString();
}
}
public void SetEdit(int edit_id, string name,double price)
{
this.EditId = edit_id;
this.EditName = name;
this.EditPrice = price;
}
}
}
Yang terjadi pada baris code FormController adalah :
- FormController selain digunakan untuk operasi insert data juga digunakan untuk operasi update dan delete data.
- FormController memiliki variabel EditId, EditName dan EditPrice. Ketiga variabel tersebut digunakan untuk menyimpan nilai data yang akan di update/delete yaitu nilai id, name dan price -nya.
- Jika nilai pada EditId bernilai 0 (nol) artinya FormController sedang menjalankan proses untuk input data, sedangkan jika nilai EditId bernilai lebih dari 0 (nol) artinya FormController sedang menjalankan fungsi untuk update data.
- Ketika screen terbuka maka akan menjalankan fungsi “InitializeBar” dan “InitializeData”.
- InitializeBar() akan menambahkan top bar menu yaitu menu “Save” (digunakan untuk menyimpan data yang sudah di input) dan menu “Trash” (digunakan untuk menghapus data yang telah dipilih). Menu “Trash” hanya ditampilkan jika FormController dalam mode update data (EditId bukan 0 nol) bukan insert data.
- Jika tombol “Save” dipilih, maka terdapat dua opsi proses yang dijalankan. Opsi pertama jika nilai EditId == 0, maka akan dijalankan proses insert data baru. Jika tidak maka akan dijalankan proses untuk memperbaharui data yang sudah ada sesuai dengan EditId yang ada.
- InitializeData() akan dijalankan jika nilai EditId lebih dari 0 (nol) yang artinya FormController saat ini sedang dalam mode update data.
Saat aplikasi dijalankan, anda akan melihat list data yang berasal dari server REST API dan anda dapat menambahkan data baru untuk diinput pada server. Bagaimana dengan proses delete dan update? Agar dapat menjalankan proses Update dan Delete, masukkan fungsi berikut pada class “FoodAdapter” :
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
parent.EditPosition = indexPath.Row;
parent.PerformSegue(“editSegue“, parent);
}
Fungsi diatas akan mengeset nilai “EditPosition” pada MainController agar MainController dapat mengetahui data yang mana yang ingin diperaharui oleh user. Kemudian pada MainController perbaharui fungsi PrepareForSegue seperti berikut :
public override void PrepareForSegue(UIStoryboardSegue segue, NSObject sender)
{
base.PrepareForSegue(segue, sender);
if (segue.Identifier == "editSegue")
{
var vc = segue.DestinationViewController as FormController;
if (EditPosition >= 0)
{
FoodMenu temp = this.datas[EditPosition];
vc.SetEdit(temp.Id, temp.Name, temp.Price);
}
}
}
Ketika proses segue dijalankan aplikasi akan memeriksa jika nilai “EditPosition” > 0 maka peralihan segue akan memanggil fungsi “SetEdit” yang pada FormController dimana guna dari fungsi tersebut adalah untuk melempar data FoodMenu yang ingin diperbaharui..
Selesai..
Silahkan jalankan program anda…
Silahkan lihat langsung code saya di https://github.com/sabithuraira/tutor_silex
Komentar