数据不会填充 UICollectionView 滚动视图

Data won't populate the UICollectionView scroll view

我是新手所以请放轻松!

我的问题如下:

我正在尝试使用来自 firebase 的数据填充滚动视图 (UICollectionView)。

我确信它正在成功检索数据,因为我可以在 firebase 函数末尾使用 for 循环打印数据。

问题是,当我尝试将数据插入滚动视图时,它说数据超出范围!!

有人向我指出,scrollview 填充了我在下面显示的 scrollView 委托方法。

也有人向我指出我的数据源是'self.pages'。如何将从 firebase 检索到的数据传递给委托方法?

Fatal error: Index out of range

这是我的代码:

//arrays of names and descriptions which are populated in firebase() function
    var names:[String] = []
    var descriptions: [String] = []

页面class:

 let imageName: UIImage
 let headerText: String
 let bodyText: String 

这里是viewDidLoad

override func viewDidLoad() {
        super.viewDidLoad()

        firebase()
        setupImages()
    }

这里是图像设置函数:

 func setupImages(){

        self.pages = [
            Page(imageName: self.image, headerText: names[0], bodyText: descriptions[0]),

            Page(imageName: self.image, headerText: names[1], bodyText: descriptions[1]),

            Page(imageName: self.image, headerText: names[2], bodyText: descriptions[2]),

            Page(imageName: self.image, headerText: names[3], bodyText: descriptions[3]),

            Page(imageName: self.image, headerText: names[4], bodyText: descriptions[4]),
        ]

        self.collectionView?.backgroundColor = .white
        self.collectionView?.register(PageCell.self, forCellWithReuseIdentifier: "cellId")
        self.collectionView?.isPagingEnabled = true
    }

我认为问题是由于 Firebase 数据检索不够快造成的。

我这样说是因为我在另一个 class 中有另一个函数似乎可以设置它:

override init(frame: CGRect) {
        super.init(frame: frame)
        //setup layout sets up constraints for the layout of the page
        setupLayout()
    }

添加 UICollectionViewDataSource 方法的:

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return pages.count
    }

和:

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! PageCell

        let page = pages[indexPath.item]
        cell.page = page
        return cell
    }

Firebase 检索方法:

func firebase()
    {
        //connection to firebase for the names and descriptions
        let db = Firestore.firestore()
        db.collection(restaurauntName).getDocuments { (snapshot, err) in

            if let err = err {
                print("Error getting documents: \(err)")
            } else {
                for document in snapshot!.documents {
                    let name = document.get("Name") as! String
                    let description = document.get("Description") as! String
                    //Add names and descriptions to the arrays
                    self.names.append(name)
                    self.descriptions.append(description)
                }
            }

            for x in self.names{
                print(x)
            }

        }
    }

感谢您的阅读,如果有人能告诉我正确的方向,我们将不胜感激!

查看您的代码:您正在使用 self.pages 作为数据源。我在此处提供的代码中看不到与 Firebase 的连接。

错误也可能来自您在传入页面时如何设置单元格

cell.page = page

要快速调试,您可以注释掉该行并查看错误是否消失。

问题来了,你的假设是正确的;代码的顺序不正确。

override func viewDidLoad() {
   super.viewDidLoad()

   firebase()
   setupImages()
}

Firebase 是异步的,您的应用程序需要以一种仅尝试在调用后的闭包内使用 Firebase 数据的方式构建。在您的 viewDidLoad 函数中,您调用 firebase() 来加载数据,但 setupImages 函数实际上会在 Firebase 有时间从服务器获取数据之前执行。

幸运的是,这是一个简单的修复。下面是一些更新名称的新函数,使流程更加清晰

override func viewDidLoad() {
   super.viewDidLoad()

   self.loadDataFromfirebase()
}

然后

func loadDataFromFirebase() {
   let db = Firestore.firestore()
   db.collection(restaurauntName).getDocuments { (snapshot, err) in
      if let err = err {
         print("Error getting documents: \(err)")
         return
      } else {
         for document in snapshot!.documents {
            let name = document.get("Name") as! String
            let description = document.get("Description") as! String
            self.names.append(name)
            self.descriptions.append(description)
         }
         self.setupImages() //safe to do this here as the firebase data is valid
         self.collectionView.reloadData()
      }
   }
}

我担心的是如果有 25 个文档...您的 setupImages 仅访问前 5 个。同样,如果有 3 个文档,应用程序将崩溃,因为该函数将尝试访问索引 3、4 处的对象而那些将不存在。