防止偷懶Day25
在完成註冊手續之後
接下來就是讓使用者可以新增隊伍然後在HomeController會去Fetch使用者新增過的隊伍資料
然後用tableView顯示出來
第一步先來看看目前想到在Database儲存資料的形式
User的地方是昨天處理好的部分,當使用者註冊時會將資料儲存在一個uid底下
包含了使用者的email跟name這兩項資訊
而今天要讓使用者在新增球隊資訊之後
會在Team底下創造一個tid,裡面會儲存球隊名稱的字串TeamName
以及這個team屬於哪個使用者的uid
開工第一步先來把該有的工具準備好
在Model裡面新增一個定義User這個class的new file
命名成User.swift
然後修改一下Team.swift這個class的內容
內容如下
Team.swift
1 2 3 4 5 6
| import UIKit
class Team: NSObject { var uid: String? var teamName: String? }
|
User.swift
1 2 3 4 5 6 7
| import UIKit
class User: NSObject { var name: String? var email: String? var uid: String? }
|
然後來到要處理資料的HomeController
一樣先看看程式碼再來一步一步處理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
| import UIKit import Firebase
class HomeController: UITableViewController { let cellId = "cellId" var teams = [Team]() var user = User() override var prefersStatusBarHidden: Bool { return false } override func viewDidLoad() { super.viewDidLoad() let newTeamButton = UIBarButtonItem(title: "New Team", style: .plain, target: self, action: #selector(toSetNewTeamController)) navigationItem.rightBarButtonItem = newTeamButton let logoutButton = UIBarButtonItem(title: "Logout", style: .plain, target: self, action: #selector(handleLogout)) navigationItem.leftBarButtonItem = logoutButton checkUserIsLogin() } func fetchTeam() { FIRDatabase.database().reference().child("Team").observe(.childAdded, with: { (snapshot) in if let dictionary = snapshot.value as? [String: AnyObject] { let team = Team() team.setValuesForKeys(dictionary) if team.uid == self.user.uid { self.teams.append(team) }
DispatchQueue.main.async { self.tableView.reloadData() } print(team.teamName as Any, team.uid as Any) } }, withCancel: nil) } func checkUserIsLogin() { if FIRAuth.auth()?.currentUser?.uid == nil { perform(#selector(handleLogout), with: nil, afterDelay: 0) } else { fetchUserSetNavBarTitle() } } func fetchUserSetNavBarTitle() { guard let uid = FIRAuth.auth()?.currentUser?.uid else { return } FIRDatabase.database().reference().child("User").child(uid).observeSingleEvent(of: .value, with: { (snapshot) in print(snapshot) if let dictionary = snapshot.value as? [String: Any] { self.user.uid = snapshot.key self.navigationItem.title = dictionary["name"] as? String self.fetchTeam() } }, withCancel: nil) } func handleLogout() { do { try FIRAuth.auth()?.signOut() } catch let logoutError { print(logoutError) } self.teams.removeAll() let loginController = LoginController() loginController.homeController = self present(loginController, animated: true, completion: nil) } func toSetNewTeamController() { let alertController = UIAlertController(title: "Add New Team", message: "", preferredStyle: .alert) let saveAction = UIAlertAction(title: "OK", style: .default, handler: { alert -> Void in let firstTextField = alertController.textFields![0] as UITextField let controller = SetNewTeamController() if firstTextField.text! != "" { controller.teamTitle = firstTextField.text! let uid = self.user.uid let ref = FIRDatabase.database().reference().child("Team") let teamRef = ref.childByAutoId() let value: [AnyHashable: Any] = ["TeamName": firstTextField.text!, "uid": uid as Any] teamRef.updateChildValues(value) self.present(UINavigationController(rootViewController: controller), animated: true, completion: nil) } else { return } }) let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: { (action : UIAlertAction!) -> Void in }) alertController.addTextField { (textField : UITextField!) -> Void in textField.placeholder = "Enter Team Name" } alertController.addAction(saveAction) alertController.addAction(cancelAction) self.present(alertController, animated: true, completion: nil) } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return teams.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = UITableViewCell(style: .subtitle, reuseIdentifier: cellId) cell.textLabel?.text = teams[indexPath.row].teamName return cell } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let controller = SetNewTeamController() controller.teamTitle = teams[indexPath.row].teamName present(UINavigationController(rootViewController: controller), animated: true, completion: nil) } }
|
第一步當然是實作讓使用者新增資料到Database上
之前在toSetNewTeamController
這個function裡面實作了當使用者點擊右上方的Add Member時
會跳出一個AlertController讓使用者輸入新增球隊的名稱
在第87~91行我們讓使用者把現有的uid跟新增的teamName儲存到Database上的Team節點下
並自動產生一個id當子樹,不過這裡的uid怎麼來的?
當然我們就需要剛剛準備好的工具拉
第7, 8行實作一個teams來儲存Fetch到的Team內容
以及一個user來儲存Fetch到的User內容
接下來在fetchUserSetNavBarTitle
這個function裡面第56行儲存使用者的uid
這樣就有自己的uid可以使用拉
然後就來實作Fetch隊伍資料的fetchTeam
這個function
首先,fetchTeam
會在fetchUserSetNavBarTitle
拿到使用者的資訊之後執行
以確保自己儲存的uid不會是空值
當fetchTeam
執行時會去Database觀察Team這個子樹下的資料
如果裡面的uid跟現在使用者的uid是一樣的
就代表這隻Team是這個使用者所創建的
那就把這筆資料儲存到前面創好的teams裡面
最後重新整理現在的tableView內容
p.s.這裡要記得UI必須在主線程裡更新
但我們還沒處理tableView的內容
所以就修改一下numberOfRowsInSection
回傳儲存的隊伍數量teams.count
以及cellForRowAt
讓cell的文字顯示隊伍名稱teamName
還有didSelectRowAt
所傳送的teamTitle
最後要記得處理當使用者登出時要把teams的內容移除
不然登入其他帳號時teams的內容可能還會儲存在裡面