困擾了快一個禮拜的 table view cell 傳值總算找到解法...一開始以為用 UserDefaults 的方法就可以解決,但是 UserDeafaults 的方法無法紀錄是哪個 cell 點選,所以最後還是只能選擇 delegate 的方式傳值。
網路上提供傳值的方法有很多種,大家可以參考下方資料
大家請參考我的文章 Day14 - 標籤列控制器 步驟1~4,新增一個含有三個標籤頁的 tab bar controller
效果如下
最上方是一個 Navigation Bar,中間是 Table View,最下面當然是 Tab Bar
Navigaion Bar 和 Table View 裡面各有一些元件要另外拉
檔案命名為 drinkViewController,裡面要遵守 UITableViewDelegate、UITableViewDataSource原則
class drinkViewController: UIViewController, UITableViewDataSource
{
//... 程式碼略
}
table view code 設定如下
ps: cell identifier 命名為 "drinkCell"
let teaList = ["茉莉綠茶", "阿薩姆紅茶", "四季春茶", "黃金烏龍", "微檸檬 紅/青", "檸檬 綠/青", "梅果綠", "8冰綠", "養樂多綠", "蜂蜜綠", "芒果青", "冰淇淋紅茶", "鮮柚綠", "波霸 紅/綠/青/烏", "波霸奶茶(大顆)", "波霸奶綠(大顆)", "珍珠 紅/綠/青/烏", "珍珠奶茶(小顆)", "珍珠奶綠(小顆)", "椰果奶茶", "仙草奶凍", "鮮柚汁(季節限定)"]
// 設定幾個 section
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
// 設定每個 section 幾個 cell
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return teaList.count
}
// 設定 cell顯示內容
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// ... 程式碼略
return cell
}
在 storyboard 中,令 Item 1 要符合 drinkViewController的類別
檔案命名為 DrinkTableViewCell
在 class DrinkTableViewCell 外,新增一個 protocol,內含一個方法 "buttonTapped"
protocol DrinkTableViewCellDelegate: class {
func buttonTapped(cell: DrinkTableViewCell, teaCount: Int)
}
在class DrinkTableViewCell內加入元件連結,並覆寫prepareForReuse()方法
class DrinkTableViewCell: UITableViewCell {
var teaCount: Int = 0
var delegate: DrinkTableViewCellDelegate?
@IBOutlet weak var teaNameLabel: UILabel!
@IBOutlet weak var teaCountLabel: UILabel!
@IBAction func teaCountStepper(_ sender: UIStepper) {
teaCount = Int(sender.value)
//teaCountLabel.text = teaCount 如果購買數字寫在這,就會出現 Day18 所說的bug
// 呼叫代理,並由 DrinkTableView.swift中實現 (實作方法下一步驟才寫)
self.delegate?.buttonTapped(cell: self, teaCount: teaCount)
}
// 覆寫 prepareForReuse()方法
override func prepareForReuse() {
super.prepareForReuse()
self.delegate = nil
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
在 storyboard 中,令 Item 1 中的 Table View 裡的 Table View Cell 要符合 DrinkTableViewCell 的類別
令 class drinkViewController 額外遵守 DrinkTableViewCellDelegate 的協議
class drinkViewController: UIViewController, UITableViewDataSource, UITableViewDelegate , DrinkTableViewCellDelegate
{
// ...程式碼略
}
將 table view 元件連結進 class drinkViewController,並實現協議 DrinkTableViewCellDelegate 的 function
@IBOutlet weak var teaTableView: UITableView!
class drinkViewController: UIViewController, UITableViewDataSource, UITableViewDelegate , DrinkTableViewCellDelegate
{
// ...部分程式碼略
var selectTeaCount: [Int] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
func buttonTapped(cell: DrinkTableViewCell, teaCount: Int){
// 就是這一步驟,讓程式可以紀錄是哪個 cell 的按鈕被點了
guard let indexPath = self.teaTableView.indexPath(for: cell) else {
// Note, this shouldn't happen - how did the user tap on a button that wasn't on screen?
return
}
selectTeaCount[indexPath.row] = teaCount
// 這邊 reloadData 是因為希望使用者按下 cell 裡面的 stepper 後,數字能及時更新到 cell 裡的 teaCountLabel
teaTableView.reloadData()
}
cell呈現內容,將 func tableView(cellForRowAt indexPath:)改寫
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "drinkCell", for: indexPath) as! DrinkTableViewCell
cell.teaNameLabel?.text = teaList[indexPath.row]
cell.teaCountLabel?.text = "\(selectTeaCount[indexPath.row])"
// 這裡的 self 是指 drinkViewController了
cell.delegate = self
return cell
}
困擾了好幾天的 bug 總算解決,明天再來把儲值的陣列整理整理,並傳到購物車頁面呈現