我試圖從Firestore(谷歌資料庫)加載資料,并希望在tableview上顯示。
所以在第一個VC中,通過prepare函式,從資料庫中獲取資料,并轉移到第二個VC(tableview)。我知道prepare函式在viewdidload之前,在我的應用程式中,prepare函式在第二個VC加載之后。
下面是我的代碼。
第一個VC
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let docRef = db.collection("Posting").getDocuments(){(querySnapshot, err)in
if let err = err{
print("errror getting documents"/span>)
}else{
for document in querySnapshot!.document{
print("(document.documentID) => (document.data())")
self.savePostings.append(document.data()
}
print(")
(self.savePostings)")
}
let vc = segue.destination as! PostingListTableViewController
vc.upedPostings = self.savePostings
vc.testPrint = "? ???"/span>
print("?? ?? ??)
(vc.upedPostings)
(self.savePostings)")
}
}
第二個VC(表視圖)
class PostingListTableViewController。UITableViewController {
//private var postings: Array<[String:Any]> = []
private var documents: [DocumentSnapshot] = [] 。
var updatedPostings: Array<[String:Any]? > = []
var testPrint:String = ""
override func viewDidLoad() {
super.viewDidLoad()
print("view did load"/span>)
//取消以下一行,以保持在演示文稿之間的選擇。
///self.clearsSelectionOnViewWillAppear = false。
//取消對以下行的注釋,以便在該視圖控制器的導航欄中顯示一個編輯按鈕。
//self.navigationItem.rightBarButtonItem = self.editButtonItem。
}
//MARK: - 表視圖資料源。
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning 不完整的實作,回傳部分的數量。
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning 不完整的實作,回傳行數。
return updatedPostings.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myTableCell", for: indexPath)
cell.textLabel?.text = updatedPostings[indexPath.row]! ["text"] as! String[/span
//配置單元格...
return cell
}
}
uj5u.com熱心網友回復:
正如@vadian所言,你的問題在于你正在進行一個異步呼叫。
prepare(for segue在viewDidLoad之前被呼叫,但是你在之后的一段時間內更新了你的屬性,當你的請求完成時,這是在viewDidLoad之后。
我建議你用下面的方法來代替它:
移除你的segue,添加識別符號到目標視圖控制器中
在
tableView:didSelectRowAtIndexPath:內運行你的getDocuments(或者在IBAction內,如果這是一個按鈕segue)2.1. 你可以顯示一些進度指示器,這樣用戶就會知道延遲的原因
。在完成后,使用instantiateViewControllerWithIdentifier從故事板創建你的視圖控制器,并手動展示它。在這種情況下,你不需要等待
prepare(for segue來設定你的屬性。
如果你的segue是從單元格中呼叫的,你可以將你的視圖控制器添加為一個委托,像這樣:
然后你需要將你的視圖控制器與UITableViewDelegate一致,當用戶按下一個單元格時,didSelectRowAt方法將被呼叫。你可以從indexPath.row中獲得單元格的編號
extension PostingListTableViewController。UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let docRef = db.collection("Posting").getDocuments(){(querySnapshot, err)in
if let err = err{
print("errror getting documents"/span>)
}else{
for document in querySnapshot!.document{
print("(document.documentID) => (document.data())")
self.savePostings.append(document.data()
}
print(")
(self.savePostings)")
}
//不確定getDocuments的完成是否在主執行緒上呼叫,如果是的話--你不需要這一行。
DispatchQueue.main.async {
let vc = storyboard!。 instantiateViewController(identifier: "storyboard_identifier") 作為! PostingListTableViewController。
vc.upedPostings = self.savePostings
vc.testPrint = "? ???"/span>
present(vc, animated: true)
print("?? ?? ??)
(vc.upedPostings)
(self.savePostings)")
}
}
}
如果你是從一個普通的按鈕,而不是從一個單元格來執行這個轉場,你可以用@IBAction來做同樣的事情。

@IBAction @objc func push() {
let docRef = db.collection("Posting").getDocuments(){(querySnapshot, err)in
if let err = err{
print("errror getting documents"/span>)
}else{
for document in querySnapshot!.document{
print("(document.documentID) => (document.data())")
self.savePostings.append(document.data()
}
print(")
(self.savePostings)")
}
//不確定getDocuments的完成是否在主執行緒上呼叫,如果是的話--你不需要這一行。
DispatchQueue.main.async {
let vc = storyboard!。 instantiateViewController(identifier: "storyboard_identifier") 作為! PostingListTableViewController。
vc.upedPostings = self.savePostings
vc.testPrint = "? ???"/span>
present(vc, animated: true)
print("?? ?? ??)
(vc.upedPostings)
(self.savePostings)")
}
}
uj5u.com熱心網友回復:
我首先要做的是DELETE?,你可能是通過從VC1上的按鈕拖放到VC2上創建的segue。用一個普通的segue代替它,它沒有連接到任何UI組件,這樣你就可以在代碼中手動觸發它(從它的識別符號,不要忘記提供一個)。它將允許你首先執行一些異步代碼,并且只有在獲得回呼時才觸發導航(如果資料獲取成功)。
要創建這樣一個分離:
這是為分隔符準備的,但現在,何時觸發它?
- 在按鈕上創建一個 @IBAction,它將觸發獲取和導航(或類似的,如 didSelectRowAtIndexPath) 。
- 這個IBAction應該呼叫另一個方法,就像下面這樣: 。
private func fetchPostingAndNavigateIfSuccessful() {
//可能應該先將活動指標設定為`.startAnimating()`。
let docRef = db.collection("Posting") 。 getDocuments() { [weak self] querySnapshot, error in
//可能應該將活動指標設定為`.stopAnimating()`。
guard錯誤 != nil。
let documents = querySnapshot? .document else {
print("error getting documents") //大概是一個顯示警告的好地方。
return。
}
let postingsData = documents.map { $0.data() > }
self?.performSegue(withIdentifier: "NavigateToPostingsSegue"/span>, sender: postingsData)
}
}
你對segue的準備將看起來像這樣:
。
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if let postingListTableViewController = segue. destination as? PostingListTableViewController。
let postingsData = sender as? [[String:Any] ] {
postingListTableViewController.upedPostings = postingsData
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/311717.html
標籤:
下一篇:面試問反射 你能跟面試官聊多少呢
