[Swift] 可不可訂購APP

練習使用 Tab Bar Controller 與 TableView 製作 APP

1、拉一個 Tab Bar Controller
2、在 Menu 與 Cart View Controller 上拉兩個 Table View
3、在 Table View 中設計 Cell 的樣式與排版
4、新增 MenuViewController.swift 與 CartViewController.swift,並將 Menu 與 Cart View Controller 設定對應的 Class,並將 tableView 拉線至檔案中
5、新增 MenuTableViewCell.swift 與 CartTableViewCell.swift,並設定對應的 Table View Cell 的 Class,同時設定 Table View Cell 的 Identifier,並將 Cell 中的 ImageView 與 Label 拉線至檔案中,以便後續的資料處理。
6、開一個新的 View Controller,並且從 Table View Cell 拉線過去,選取 Show,新增 OptionsViewController.swift 檔案,並設定這個 View Controller 的 Class 為 OptionsViewController,以及設定線的 Identifier 為showOptions
7、新增 Item.swift 裡面定義 Item 的 class
8、設定 API_URL,繼上次使用的菜單 API,本次多新增一個 Google Sheet 用於儲存購物車,一樣可以使用 Google Apps Script 操作,API_URL 會回傳 JSON 格式的菜單資訊,CART_API_URL 會記錄目前收到的飲料訂單

設定對應 Class
拉好對應 Outlet
設定 Identifier
Table View Cell 拉線並選取 Show
在 Info.plist 新增 API 網址:API_URL, CART_API_URL
CART_API_URL 之試算表內容
// pass data from MenuViewController to OptionsViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showOptions" {
let optionsVC = segue.destination as? OptionsViewController
if let row = tableView.indexPathForSelectedRow?.row{
optionsVC?.selectedItem = itemArray[row]
}
}
}
// send GET & POST request by fetchMenuItems
func fetchMenuItems() {
self.activityIndicator.isHidden = false
self.activityIndicator.startAnimating()
guard let url = URL(string: Bundle.main.object(forInfoDictionaryKey: "CART_API_URL") as! String) else { return }
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data, error == nil else {
print("Error fetching data: \(String(describing: error))")
return
}
do {
let decodedData = try JSONDecoder().decode([drink].self, from: data)
DispatchQueue.main.async {
self.cart = decodedData
self.tableView.reloadData()
self.activityIndicator.isHidden = true
self.activityIndicator.stopAnimating()
print(decodedData[0])
}
} catch {
print("Error decoding data: \(error)")
self.activityIndicator.isHidden = true
self.activityIndicator.stopAnimating()
}
}
task.resume()
}
// send order by POST request
func sendPostRequest(size: String, itemName: String, iceLevel: String, sugarLevel: String, topping: String, price: Int) {
self.addButton.isHidden = true
self.activityIndicator.isHidden = false
self.activityIndicator.startAnimating()
guard let url = URL(string: Bundle.main.object(forInfoDictionaryKey: "CART_API_URL") as! String) else {
print("Invalid URL.")
return
}

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")

do {
let postData: [String: Any] = [
"size": size,
"itemName": itemName,
"iceLevel": iceLevel,
"sugarLevel": sugarLevel,
"topping": topping,
"price": price
]
let jsonData = try JSONSerialization.data(withJSONObject: postData, options: [])
request.httpBody = jsonData
} catch {
print("Error encoding JSON data: \(error)")
return
}

let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error with request: \(error)")
return
}

guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print("Server error")
return
}

if let data = data, let responseString = String(data: data, encoding: .utf8) {
print("Response: \(responseString)")
self.addButton.isHidden = false
self.activityIndicator.stopAnimating()
self.activityIndicator.isHidden = true
}
}

task.resume()
}

一些待改善的功能留著下次做

GitHub:

--

--