数据不会填充 UICollectionView 滚动视图

Posted

技术标签:

【中文标题】数据不会填充 UICollectionView 滚动视图【英文标题】:Data won't populate the UICollectionView scroll view 【发布时间】:2020-01-17 01:29:45 【问题描述】:

我是新手,所以请放轻松!

我的问题如下:

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

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

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

有人向我指出,滚动视图填充了我在下面显示的滚动视图委托方法。

还有人指出我的数据源是“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] = []

页面类:

 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 数据。

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

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)
            

        
    

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

【问题讨论】:

如果能共享tableView委托方法和数据源就好了。 @Kanongata 我不相信我有一个 tableView 代表,你说的数据源是什么意思?我已经展示了如何从 firebase 获取数据? @mike 他的意思是 UICollectionViewDataSource 方法的 @byaruhaf 我在哪里可以找到它?抱歉,这是一个愚蠢的问题? numberOfItemsInSectioncellForItemAt 的 collectionView 函数 【参考方案1】:

这就是问题所在,您的假设是正确的;代码没有按正确的顺序流动。

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 和那些不会存在。

【讨论】:

嗨,Jay,效果很好!非常感谢你在这方面坚持我!当我在项目的其他方面工作时,这几天一直让我头疼!我不担心只有 5 个文件,因为每次都会有 5 个确定!再次感谢您! 虽然它正在工作,但在加载内容之前屏幕变黑了?这又是一个异步问题吗? @mike 屏幕变黑了?您能否详细说明一下,好像您的屏幕变黑了,这听起来与您的视图或其他东西完全不同。 很抱歉再次打扰您!基本上当我运行应用程序时,屏幕变黑,就像这里的视频一样:youtube.com/watch?v=xLOwMYdUKeg @mike 您的视图设置方式似乎存在问题。我会在这一行 setupLayout 上放一个断点,看看它是在之前还是之后变黑,然后一次从那里遍历代码,看看是什么原因造成的。【参考方案2】:

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

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

cell.page = page

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

【讨论】:

感谢您的回复!我已经尝试了这两种解决方案,但没有任何结果:(你还有其他想法吗? 为什么投反对票?无论如何,您将需要提供更多代码。您试图在某个地方访问超出范围的索引。它不在您在此处提供的代码中。 投反对票的不是我,我现在投了你的票。由于我是一个新的贡献者,我认为我的选票不算数。关于我可以为上下文添加哪些额外代码的任何建议?再次感谢您的帮助 OP 使用的是 collectionView,因此 indexPath.item 更普遍地用于那些。 indexPath.row 更像是一个 tableView 的东西。 没错,这只是一个故障排除的想法。两者都有效

以上是关于数据不会填充 UICollectionView 滚动视图的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView 容器填充

UICollectionView 渲染问题

UICollectionView contentOffset 错误

UICollectionView 重新加载数据不会更新单元格

Swift 3 - 带有填充的 UICollectionView 中心单元

调整 UICollectionViewCells 的大小以始终填充 UICollectionView