【问题标题】:UICollectionView is not loading cell second timeUICollectionView 没有第二次加载单元格
【发布时间】:2017-11-30 09:55:24
【问题描述】:

我照常使用UICollectionview 列出一些图片。

代码只是从 api 获取数据并异步更新 UICollectionView。 API 调用代码的结尾是用self.collectionView?.reloadData() 更新数据。

另外,当用户滚动到UICollectionView 的底部时,再次触发api 调用并更新photos 数组和collectionview 数据。但是在这第二个动作中没有向UICollectionView添加新单元格

代码如下:

class PhotoStreamViewController: UICollectionViewController {
    var photos = [Photo]()
    var pageIndex = 1
    ...


    override func viewDidLoad() {
        super.viewDidLoad()
        allPhotos()
        ...

    }
    override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        pageIndex+=1
        allPhotos()
    }


    func allPhotos() {

        let headers: HTTPHeaders = [
            "Authorization": "Client-ID APIKEY"
        ]

        var json:JSON = JSON()

        Alamofire.request("https://www.apiurl.com/photos?page=\(pageIndex)&per_page=15&order_by=latest",method: .get, parameters: nil , encoding: URLEncoding.default, headers: headers)
            .responseJSON() { (response:DataResponse<Any>) in
                //            debugPrint(response)
                switch response.result {
                case .success(let value):
                    json = JSON(value)

                    for (_,subJson):(String, JSON) in json {
                        let image = UIImage(data: try! Data(contentsOf: URL(string: subJson["urls"]["small"].stringValue)!))

                        if let photo = Photo(userName: subJson["user"]["name"].stringValue,comment: "dummy",image: image!,location: "Location",thumb: "thumb") {
                            self.photos.append(photo)
                        }
                    }

                    self.collectionView?.reloadData()


                case .failure(let error):
                    print(error)
                }
        }
    }

}

extension PhotoStreamViewController : UICollectionViewDelegateFlowLayout{

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


    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AnnotatedPhotoCell", for: indexPath as IndexPath) as! AnnotatedPhotoCell
        cell.photo = photos[indexPath.item]
        return cell
    }

}

【问题讨论】:

  • 您必须创建单独的 API 处理程序类来调用 Web 服务
  • 我认为你必须检查滚动视图的滚动视图的结束。还要检查 api 是否为您提供了每个页面所需的记录。使用 Postman 为不同的页面测试一次 API。
  • 这里有几个问题:(a) 为什么你的方法签名看起来像func allPhotos() {...} 而不是func allPhotos(forPage pageIndex: Int) {...}? (b) 为什么在获取照片后重新加载数据而不是仅重新加载新单元格? (c) 如果要重新加载数据,为什么不在主线程上重新加载?
  • a) 是的,这不是一个好习惯,但问题不是这样。感谢您的建议b) 实际上我正在尝试添加新单元格,我在互联网上的一些教程中看到了该方法。但也许你是对的,我需要改变这个方法 c) 我不明白你的意思是什么主线程

标签: ios swift uicollectionview


【解决方案1】:

您需要在主队列中重新加载您的收藏视图。请试试这个。我认为它可以解决您的问题

DispatchQueue.main.async {
    self.collectionView?.reloadData()
}

【讨论】:

  • 感谢您的回答,但我已经尝试过了。请求已经异步,所以那里没有问题。
【解决方案2】:

self.photos.append(photo)下添加这段代码后问题解决

  if(self.pageIndex > 1){
     let indexPath = IndexPath(item:self.photos.count-1, section: 0)
     self.collectionView?.insertItems(at: [indexPath])

  }

我也有类似的扩展名:

extension PhotoStreamViewController : PinterestLayoutDelegate

PinterestLayout 中自定义布局属性后效果很好

override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes?

【讨论】:

  • 有没有找到完美的解决方案?
【解决方案3】:

试试这个

if let layout = self.IBcollection?.collectionViewLayout as? PInterestLayout 
{
      layout.cache = []
      layout.columnsYoffset = []
      layout.contentSize = CGSize.zero
}
self.IBcollection.reloadData()

【讨论】:

  • 查看我的解决方案。
【解决方案4】:

打开PinterestLayout

检查prepare 函数。它包含以下行。其中cache 为空。每当它重新加载时,它都会得到cache 为空。

guard cache.isEmpty == true,let collectionView = collectionView else {return}

将上面的代码替换为:

guard let collectionView = collectionView else {return}
cache.removeAll() // Add this line while changing in array elements.

【讨论】: