#16 訂飲料 App,上傳資料到後台

Peter請的飲料喝得很開心,也該來寫作業了吧 :D
一步步紀錄我這次寫作業的流程跟心得

Debug流水帳:
*建立自定義的API:建立google sheet, 註冊sheetDB並貼上sheet url產生api url, 在程式抓api data,用JSON.decode成自定義的struct(飲料訂單的詳細資料), 定義menu.plist(飲料菜單)給UIPicker使用

*單純只用UIPickerView的話,picker會一直出現在螢幕上,而不是點擊某個地方才出現picker(適合做午餐輪盤之類的?)

UIPickerViewDelegate, UIPickerViewDataSource

*常見用法:UIPickerView跟UITextField 結合
(一樣要加UIPickerViewDelegate, UIPickerViewDataSource)
當畫面上UITextField元件有2個以上,需要用textFieldDidBeginEditing來設定給哪個元件becomeFirstResponder()
要顯示UIPickerView時需寫在DispatchQueue.main.async裡,否則不會顯示

UITextFieldDelegate
DispatchQueue.main.async{self.initDrinkPicker()}

要記得寫toolbar for UIPicker,否則UIPicker不會有下一步動作(取消/確認)
pickerView.selectRow設定picker item要先指到哪一個

textFieldShouldReturn是按enter結束編輯會執行
toolbar.isTranslucent = true看起來跟透明度有關,先不加

*新增Tab bar controller,拉segue-view controllers,拉tab bar icon改順序

*控制menu的選項(ex:熱飲限定,冰塊選項disable),試算金額

iceSegment.selectedSegmentIndex = 0
iceSegment.isEnabled = false

*送出訂單:
check名字有填?alert:請填寫訂購人姓名

let alert = UIAlertController(title: "請填寫訂購人姓名", message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alert, animated: true, completion: nil)

上傳訂單create:參考投影片,新增struct放data

struct DrinkOrderData:Encodable {
var data:DrinkOrder
}
struct DrinkOrder:Codable {
...略...
}

POST:

let drinkOrderData = DrinkOrderData(data: drinkOrder)
let url = URL(string: "https://sheetdb.io/api/v1/...略...")
var urlRequest = URLRequest(url: url!)
urlRequest.httpMethod = "POST"

alert:訂單已送出,請至購物車確認

let alert = UIAlertController(title: "訂單已送出", message: "請至購物車確認", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alert, animated: true, completion: nil)

*購物車頁面:在viewWillAppear 下載資料並顯示 order list

*刪除訂單:
參考sheetDB-DELETE, 填入column & value, 會把符合的row刪掉,當有多筆資料符合都會刪掉(建議使用較嚴格的條件,例如:orderid)

let deleteById = orderList[row].orderid
let url = URL(string: "https://sheetdb.io/api/v1/...略.../orderid/\(deleteById)")
var urlRequest = URLRequest(url: url!)
urlRequest.httpMethod = "DELETE"

*修改訂單:我做了2條路,最後使用action2
action1:performSegue顯示訂單畫面,所需資料利用prepare傳送
action2:參考同學的文章使用 puchViewController/popViewController顯示訂單畫面,自訂 isModifyState來判斷是修改訂單還是新增訂單
main.storyboard記得要加上navigation controller(沒加不會build error,但是不會動作)
navigation會有title位置,訂單畫面需要微調

傳送要修改的訂單資訊到drinkOrderViewController,相對應的選項要連動(冰塊甜度…等),送出訂單button的名稱 ->修改訂單

submitLabel.setTitle("修改訂單", for: .normal)

update, 參考sheetDB-PUT, 填入column & value, 會把符合的row修改,當有多筆資料符合都會修改(建議使用較嚴格的條件,例如:orderid)
修改完跳出alert,按ok的話執行popViewController回到上一層

let updateById = modifyDrinkOrder.orderid
let url = URL(string: "https://sheetdb.io/api/v1/...略.../orderid/\(updateById)")
var urlRequest = URLRequest(url: url!)
urlRequest.httpMethod = "PUT"

*下拉更新:
在main.stroyboard把Table View Controller的Refreshing改成Enable

override func viewDidLoad() {
super.viewDidLoad()
refreshControl?.addTarget(self, action:#selector(refreshOrderList(refreshControl:)),for: UIControl.Event.valueChanged)
}
@objc func refreshOrderList(refreshControl:UIRefreshControl){
getOrderList()
refreshControl.endRefreshing()
}

*搜尋功能:
1.新增extension XXX: UISearchResultsUpdating,UISearchBarDelegate
2.在viewDidLoad設定誰來接收delegate

tableView.tableHeaderView = searchController?.searchBar
searchController = UISearchController(searchResultsController: nil)
searchController?.searchResultsUpdater = self
searchController?.searchBar.delegate = self
searchController?.obscuresBackgroundDuringPresentation = false
navigationItem.searchController = searchController
definesPresentationContext = true

obscuresBackgroundDuringPresentation = false//搜尋結果的表格不要變暗
(dimsBackgroundDuringPresentation Deprecated in iOs 12)
definesPresentationContext = true
不設這個值乍看不會有問題,詳細請參考這篇(但我不設也沒問題@@)

3.在updateSearchResults只顯示跟搜尋有關的訂單資料

func updateSearchResults(for searchController: UISearchController) {
if let searchString = searchController.searchBar.text{
searchOrderList = orderList.filter({ (drinkOrder) -> Bool in
drinkOrder.name.lowercased().contains(searchString.lowercased())
})
tableView.reloadData()
}
}

4.傳送cell資料(有2種:orderLis, searchOrderList),以下幾個地方要改
return table.count
return cell
傳要修改的資料到修改訂單controller

if self.navigationItem.searchController?.isActive == true{
controller.modifyDrinkOrder = self.searchOrderList[indexPath.row]
}else{
controller.modifyDrinkOrder = self.orderList[indexPath.row]
}

*訂單匯總:傳送orderList到orderSettlementTableViewController計算各種飲料的杯數,並顯示總價
bar button垃圾桶:alert是否清空所有訂單資料

GitHub:

--

--