我嘗試在 tableview 中顯示來自 cloud firestore 的資料。在嘗試這個之前,我的應用程式運行良好。我有一個帶有基本單元格影像標題和每行副標題的表格視圖。也是當用戶點擊單元格時開始流式傳輸的視頻檔案的 URL。現在我希望這些單元格顯示來自 Cloud Firestore 的資料。感謝任何幫助。先感謝您。
這是在我開始嘗試列出來自云 Firestore 的資料之前一切正常的 swift 檔案。
import UIKit
import AVKit
import AVFoundation
import FirebaseFirestore
import SwiftUI
class ListOfVideoLessonsTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let pinchGesture = UIPinchGestureRecognizer()
@ObservedObject private var viewModel = VideosViewModel()
var player = AVPlayer()
var playerViewController = AVPlayerViewController()
@IBOutlet var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.viewModel.fetchData()
self.title = "Video Lessons"
table.delegate = self
table.dataSource = self
// Do any additional setup after loading the view.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("videos count = ", viewModel.videos.count)
return viewModel.videos.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let video = viewModel.videos[indexPath.row]
tableView.tableFooterView = UIView()
//configure cell
cell.textLabel?.text = video.name
cell.detailTextLabel?.text = video.lessonName
cell.accessoryType = .disclosureIndicator
let imageName = UIImage(named: video.imageName)
cell.imageView?.image = imageName!.withRenderingMode(.alwaysOriginal)
let backgroundView = UIView()
backgroundView.backgroundColor = UIColor(named: "VideoLessonsCellHighlighted")
cell.selectedBackgroundView = backgroundView
cell.textLabel?.font = UIFont(name: "Helvetica-Bold", size: 14)
cell.detailTextLabel?.font = UIFont(name: "Helvetica", size: 12)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
playVideo(at: indexPath)
}
func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.contentView.backgroundColor = UIColor(named: "VideoLessonsCellHighlighted")
cell.textLabel?.highlightedTextColor = UIColor(named: "textHighlighted")
cell.detailTextLabel?.highlightedTextColor = UIColor(named: "textHighlighted")
}
}
func tableView(_ tableView: UITableView, didUnhighlightRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.contentView.backgroundColor = nil
}
}
func playVideo(at indexPath: IndexPath){
let selectedVideo = viewModel.videos[indexPath.row]
let url = URL(string: selectedVideo.fileURL)
player = AVPlayer(url: url!)
playerViewController.player = player
self.present(playerViewController, animated: true, completion: {
self.playerViewController.player?.play()
})
}
}
我有一個 VideoViewModel.swift 檔案
import Foundation
import FirebaseAnalytics
import FirebaseFirestore
class VideosViewModel: ObservableObject {
@Published var videos = [Video]()
private var db = Firestore.firestore()
func fetchData() {
db.collection("videos").addSnapshotListener { [self] (querySnapshot, error) in
guard let documents = querySnapshot?.documents else {
print("No Documents")
return
}
self.videos = documents.map { (queryDocumentSnapshot) -> Video in
let data = queryDocumentSnapshot.data()
let name = data["name"] as? String ?? ""
let imageName = data["imageName"] as? String ?? ""
let lessonName = data["lessonName"] as? String ?? ""
let fileURL = data["fileURL"] as? String ?? ""
print(data)
return Video(name: name, imageName: imageName, lessonName: lessonName, fileURL: fileURL)
}
}
}
}
當我列印 print("videos count = ", viewModel.videos.count) 它顯示 000 個視頻,
videos count = 0
videos count = 0
videos count = 0
當我列印 print(data) 時,它顯示來自 firebase firestore 的資料。
["lessonName": Lesson Name, "name": Name, "fileURL": gs://tff-sample.appspot.com/Video Lessons/mixkit-hands-of-a-man-playing-on-a-computer-43527.mp4, "imageName": gs://tff-sample.appspot.com/Video Images/1024x1024.png]
["lessonName": LessonName, "name": Name 2, "fileURL": gs://tff-sample.appspot.com/Video Lessons/mixkit-meadow-surrounded-by-trees-on-a-sunny-afternoon-40647., "imageName": gs://tff-sample.appspot.com/Video Images/1024x1024.png]
uj5u.com熱心網友回復:
由于 ObservedObject 是為 SwiftUI 設計的,并且您的代碼使用的是 UIKit。因此,在獲取資料后,不會觀察 ViewModel 以讓 ViewController 知道是否有任何更新。要解決該問題,您可以改用 Combine。您可以訪問 @Published 屬性包裝器的預計值(通過在其名稱前加上 $ 前綴),這使我們能夠訪問僅為該屬性的組合發布者。然后,您可以使用相同的接收器 API 訂閱該發布者,如下所示:viewModel.$videos.sink
import UIKit
import AVKit
import AVFoundation
import FirebaseFirestore
import Combine
class ListOfVideoLessonsTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let pinchGesture = UIPinchGestureRecognizer()
private var viewModel = VideosViewModel()
// `AnyCancellable` belongs to Combine SDK
private var cancellable: AnyCancellable?
.......
override func viewDidLoad() {
super.viewDidLoad()
self.viewModel.fetchData()
self.title = "Video Lessons"
table.delegate = self
table.dataSource = self
// Do any additional setup after loading the view.
cancellable = viewModel.$videos.sink { _ in
DispatchQueue.main.async {
self.table.reloadData()
}
}
}
}
您需要跟蹤使用接收器啟動訂閱時組合回傳的可取消物件,因為該訂閱僅在保留回傳的 AnyCancellable 實體時才保持有效。這將避免記憶體泄漏。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/506535.html
標籤:Google Cloud Collective 代码 火力基地 谷歌云火库
上一篇:錯誤執行緒8:EXC_BAD_INSTRUCTION(code=EXC_I386_INVOP,subcode=0x0)有什么問題?
