0

下午好一切,的CollectionView:scrollToItem,reloadData,並調度隊列

我遇到了一個令人沮喪的錯誤關於我一直在下面聊天應用教程,想補救(本教程沒有解決這個問題,因爲我已經轉換爲Swift 3/Xcode8)。讓我試着描述這個問題:

兩個用戶之間的聊天日誌利用Firebase數據庫來存儲和檢索它們之間的會話消息。我正在使用collectionView來顯示對話。我想在聊天記錄中實現一項功能,這樣當用戶選擇要查看的對話時,它會滾動到最新/最後的「消息」,以便用戶輕鬆地繼續對話。

下面是聊天記錄器當前的相關代碼:

func observeMessages() { 
    guard let uid = FIRAuth.auth()?.currentUser?.uid, let toId = user?.id else { 
     return 
    } 

    let userMessagesRef = FIRDatabase.database().reference().child("user-messages").child(uid).child(toId) 
    userMessagesRef.observe(.childAdded, with: { (snapshot) in 

     let messageId = snapshot.key 
     let messagesRef = FIRDatabase.database().reference().child("messages").child(messageId) 
     messagesRef.observeSingleEvent(of: .value, with: { (snapshot) in 

      guard let dictionary = snapshot.value as? [String: AnyObject] else { 
       return 
      } 

      self.messages.append(Message(dictionary: dictionary)) 

      DispatchQueue.main.async(execute: { 
       self.collectionView?.reloadData() 

       let indexPath = IndexPath(item: self.messages.count - 1, section: 0) 

       self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true) 
      }) 

     }, withCancel: nil) 

    }, withCancel: nil) 
} 

我現在遇到的問題是關於無效indexPath爲的CollectionView滾動到。使用打印語句,我發現reloadData()被調用了很多,這只是我從調試控制檯的假設,indexPath不能「更新」或「跟上」這些值。

我對GCD很新穎(我只被告知UI的更新應該總是在主線程中完成),並且想知道我的問題的答案是否在於設置正確的同步/異步執行,或串行/併發隊列。例如:

Ex //使用後臺線程獲取會話消息並更新indexPath,而主線程異步地重載數據和scrollsToItem。

我不確定,但是如果有人能夠對此作出點亮,或者指引我朝着正確的方向發展,我會非常感激。非常感謝。

回答

1

如果基於

self.messages array, 

您的CollectionView把

self.messages.append(Message(dictionary: dictionary)) 

到主線程太多。

用於主線程表(collectionView或tableView)的所有數據列表必須僅在主線程上管理。

+0

謝謝Nikita和Sanju。我已經做出了改變,似乎緩解了所有問題。從現在開始,我一定會保留主線程中的數據列表。 – iMoment