Swift : Firestore와 collectionView를 사용하여 게시 목록 검색, 업데이트 및 삭제 처리
보다 보다 라이브러리등 있다고 생각하지만 기본적인 CollectionView의 구조만으로 해 보았다.
구체적으로는
snapshot.documentChanges
와 collectionView.insertItems(at:)
/collectionView.deleteItems(at:)
코드
import FirebaseFirestore
class ViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
var stories: [Story] = []
let db = Firestore.firestore()
var storiesListener: ListenerRegistration?
override func viewDidLoad() {
super.viewDidLoad()
self.setStoriesListener()
}
func setStoriesListener() {
self.storiesListener = self.db.collection("stories")
.order(by: "createTime", descending: true) // 降順で(日付が新しい順から)取ってくる
.addSnapshotListener({ (querySnapshot, error) in
guard let snapshot = querySnapshot else {
print("Error while getting collection: \(error)")
return
}
snapshot.documentChanges.forEach { diff in
if (diff.type == .added) {
let story = Story(document: diff.document)
let newIndex = Int(diff.newIndex)
self.stories.insert(story, at: newIndex) // 投稿を格納している配列のindexとFirestore上のindexを揃えてやる
self.collectionView.insertItems(at: [IndexPath(item: newIndex, section: 0)])
}
if (diff.type == .modified) {
// いいねやコメントなどのフィールドバリューの更新はここが呼ばれる
// リアルタイムでいいね数やコメント数の変化を反映したい場合は collectionView.reloadItems(at:)を使うはず
}
if (diff.type == .removed) {
let oldIndex = Int(diff.oldIndex)
self.stories.remove(at: oldIndex)
self.collectionView.deleteItems(at: [IndexPath(item: oldIndex, section: 0)])
}
}
})
}
extension ViewController: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.stories.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! StoryCell
let story = self.stories[indexPath.row]
// cellに画像やラベルテキストを設定する処理
return cell
}
}
덧붙여서 createTime에서 서버 타임 스탬프를 사용하고 있다고 하면
.added
뒤에 .modefied
가 곧바로 불리는 것에 주의.리스너를 설정하는 타이밍
위에서는 viewDidLoad()로 리스너를 설정하고 있어 Firebase 문서 등에서 볼 수 있는 viewWillAppear가 아니다. 이것은 홈 탭을 이동해 돌아왔을 때마다, 재취득&묘화 처리가 달리는 것을 막고 싶기 때문이다. deinit는 홈 탭의 천이에서는 불리지 않기 때문에 다른 화면에 가도 계속 관관을 계속할 수 있다.
viewWillApper에서 리스너를 설정하고 viewWillDesaper에서
storiesListener?.remove()
를 호출하지 않게 하면 탭에서 전환해 돌아올 때마다 리스너가 중복 세트 되는 것이 원인인가, 역시 매번 리로드가 달려 버린다.누군가 적절한 방법을하고 있다면 알려주세요. 🥺
reloadData()와 insertItem(at: Index)의 차이
reloadData를 호출하면
collectionView(_:cellForItemAt:)が
collectionView(_:numberOfItemsInSection)`로 반환된 횟수분, 0부터 차례로 불려 셀이 생성된다.한편으로 insertItems(at: Index)를 부르면
at
로 지정한 Index만으로 매번 collectionView(_:cellForItemAt)
가 불린다.reloadData () 그럼 왜 안돼?
addSnapshotListener로 항상 감시를 하고 있으면 뭔가의 변경은 전부 픽업한다. 그러나 그럼 , 1개 투고가 있거나 좋네요나 코멘트가 있을 때마다 모든 Cell가 재리로드되어 투고 일람 화면이 치카치카 해 보인 것이 아니게 된다.
그렇다고 해서 청취를 하지 않고 에서 루트의 View에서 추적 홈 화면
getDocuments
같은 기능을 호출하거나 collectionView를 업데이트하는 것은 어렵고 복잡한 것 같았다).그런데 많은 문헌에서는 이런 방식이 거의 없어 고전했다.
참고한 기사
insert나 delete를 이용한 깨끗한 갱신은, iOS나 Firestore등에서 신기사를 양산하고 있다 @ 물건씨의 이하 기사가 참고가 되었다.
htps : // 기 st. 기주 b. m / 0926 / 27131 8 6 1cf27 0dc4b655 240350
newIndex나 oldIndex의 정확한 이해는 Firebase 공식 문서에
htps : // 푹 빠져라. 오, ぇ. 코 m / 드 cs / 레후 렌세 / 슈 ft / 푹 푹신 푹신 s 트레 / 아피 / 르후 렌 세 / C ぁ せ s / 도쿠 멘 t 짱
Reference
이 문제에 관하여(Swift : Firestore와 collectionView를 사용하여 게시 목록 검색, 업데이트 및 삭제 처리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/maztak/items/66308f9ef8a54f899c6b텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)