#52 忙一下期未作業吧-5-訂飲料App(以可不可熟成紅茶為例)-完結篇。

程式沒完成,因為有同學已經寫好,我就很安心的慢慢寫,感謝 Min 同學。明天要上課,先寫一下目前的進度吧。目前只有單品茶的資料,先故意把字放大一點,有時間再完善程式與資料。

操作畫面

螢幕截圖

功能

主要是4個畫面

1. 首頁 UI
2. 飲料列表頁
3. 飲料客製畫面
4. 團友們的訂單列表

學習目標

  • 客製化 tableViewCell
  • Auto Layout、StackView
  • Airtable 創建訂單資料
  • Airtable API串接,Struct + JSON
  • Postman 測試 API+CRUD
  • UIAlertController
  • Kingfisher
  • segue傳值
  • Delegate

飲料列表頁

使用二個不同的 tableViewCell 來顯示型錄。

字有點小,應該之後點小圖應該可以看一下大圖,然後可以一頁只看一個單品的資訊,字就可以放大,不過還沒不及做。

飲料客製畫面

更新金額

點了中杯或大杯,或是增加配料,上面的Cell要重新顯示新的金額。

修改姓名

當使用者在下面的客製飲料設定 cell 修改姓名時,希望能在上面的訂單預覽 cell,同步顯示修改的姓名。

練習用 Delegate 代理機制來實現。有點複雜記錄一下,大概要8個步驟,請看註解。

UserSelectTableViewCell

// 1- 建立protocol,用來通知 tableViewController 使用者改了名字
protocol UserSelectTableViewCellDelegate: AnyObject {
func userSelected(_ newUserId: String?)
}

// 2- 加 UITextFieldDelegate
class UserSelectTableViewCell: UITableViewCell, UITextFieldDelegate {
weak var delegate: UserSelectTableViewCellDelegate?

override func awakeFromNib() {
super.awakeFromNib()
...
// 3- 設定userIdTextField.delegate,追蹤使用者修改名字 UITextFieldDelegate
userIdTextField.delegate = self
}

// MARK: - UITextFieldDelegate
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let newUserId = (textField.text as NSString?)?.replacingCharacters(in: range, with: string)

// 4- 使用者輸入時,通知委託
delegate?.userSelected(newUserId)
return true
}
}

UserSelectTableViewController

// 5- 加入 UserSelectTableViewCellDelegate
class UserSelectTableViewController: UITableViewController, UserSelectTableViewCellDelegate {


// 6- 加入 UserSelectTableViewCellDelegate function
func userSelected(_ newUserId: String?) {
print("userSelected newUserId = \(newUserId)")
// 在這裡處理選擇的使用者ID,並更新相對應的 OrderDetailTableViewCell
if let newUserId {
orderDetails[0].fields.userId = newUserId

// 8- 只更新第一個 section 的第一個 row, 不要有動畫避免閃爍
let indexPath = IndexPath(row: 0, section: 0)
tableView.reloadRows(at: [indexPath], with: .none)
}
}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// 創建一個UITableViewCell

var cell: UITableViewCell

if indexPath.row % 2 == 1 {
//下面的客製飲料設定 cell
cell = tableView.dequeueReusableCell(withIdentifier: "UserSelectTableViewCell", for: indexPath) as! UserSelectTableViewCell

if let userSelectCell = cell as? UserSelectTableViewCell {
// 7- 設定 cell 的 delegate
userSelectCell.delegate = self
}
} else {
//上面的訂單預覽 cell
cell = tableView.dequeueReusableCell(withIdentifier: "PreviewOrderDetailTableViewCell", for: indexPath) as! OrderDetailTableViewCell
if let cell = cell as? OrderDetailTableViewCell {
let orderDetail = orderDetails[indexPath.row]
// 設定 cell 的顯示內容
...
}
}

return cell ?? UITableViewCell()
}
}

#菓玉無法做熱飲

官網說明裡有一個條件 "菓玉無法做熱飲",順便也加上去,當使用者點了熱飲,就自動把 『菓玉』的按鍵取消並且 isEnabled=fasle 不能點選,點了其他溫度就恢復『菓玉』按鍵可以點擊。

確認送出訂單

檢查姓名是否有填寫,提醒使用者輸入姓名。

訂單成功建立,顯示成功訊息。

訂單失敗,顯示失敗訊息。目前所有失敗都先當成沒網路。

團友們的訂單列表

團友們的訂單列表花了一點時間來處理多個 section 的設計,目前會依日期,同一天的訂單會被分在同一個 section,例如有 “2024/01/03”, “2024/01/02”, “2024/01/01” 三天的訂單,就會有三個 section。排序上會以最近的時間排在最上面,方便你下完訂單,回來檢查時,可以在前幾筆就找到你的訂單確認。

目前不能刪和修改訂單,哈,下好離手。

登入及註冊

未實作

API Key 的處理

傳到Github會有 API Key 的問題,之後還要研究一下怎麼處理

專案歷程

參考

--

--