UICollectionView reloadData()不更新集合视图中的单元格

时间:2017-02-15 05:50:18

标签: ios swift3 uicollectionview

这是我正在努力实现的高级描述; 1.获取数据 2.将获取的数据保存在数组对象中 3.使用数组的大小更新集合视图

这是我的代码

class ItemcollectionViewController:UICollectionViewController, UICollectionViewDelegateFlowLayout {

  let cellId = "CellId"
  var categories = [Category]()
  let viewOptionVar:ViewOptionBar = {
      let vOV = ViewOptionBar()
      vOV.translatesAutoresizingMaskIntoConstraints = false
      return vOV
  }()

  private func fetchData() {
      let categoryController = CategoryController()
      categoryController.getAllCategory(username: "blah", password: "password") {(returnedCategories, error) -> Void in
            if error != nil {
               print(error)
               return
            }
            self.categories = returnedCategories!
            print("size of the array is \(self.categories.count)")
            OperationQueue.main.addOperation{self.collectionView?.reloadData()}
      }

  }

  override func viewDidLoad() {
    super.viewDidLoad()
    fetchData()
    collectionView?.backgroundColor = UIColor.white
    collectionView?.register(ItemCell.self, forCellWithReuseIdentifier: cellId)
    collectionView?.contentInset = UIEdgeInsetsMake(50, 0, self.view.frame.height, self.view.frame.width)
    collectionView?.scrollIndicatorInsets = UIEdgeInsetsMake(50, 0, 0, self.view.frame.width)
  }

  override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    print("in the method \(self.categories.count)")
    return self.categories.count
  }

  override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! ItemCell
    cell.category = categories[indexPath.item]
    return cell
  }

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: 111, height: 111)
  }

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 0
  }

  private func setupViweOptionBar() {
    view.addSubview(viewOptionVar)
    view.addConstraintsWithFormat(format: "H:|[v0]|", views: viewOptionVar)
    view.addConstraintsWithFormat(format: "V:|[v0(50)]", views: viewOptionVar)
  }
}

在日志中我可以看到以下声明:

  方法0中的

     

数组的大小为3

并且从我的视野中看不到任何单元格。

有人可以告诉我我做错了什么吗? 提前谢谢。

编辑1 现在我在注册自定义单元格后获取数据。但是,它仍然无效

更新代码:

class ItemcollectionViewController:UICollectionViewController, UICollectionViewDelegateFlowLayout {

  let cellId = "CellId"
  var categories = [Category]()
  let viewOptionVar:ViewOptionBar = {
      let vOV = ViewOptionBar()
      vOV.translatesAutoresizingMaskIntoConstraints = false
      return vOV
  }()

  private func fetchData() {
      let categoryController = CategoryController()
      categoryController.getAllCategory(username: "blah", password: "password") {(returnedCategories, error) -> Void in
            if error != nil {
               print(error)
               return
            }
            self.categories = returnedCategories!
            print("size of the array is \(self.categories.count)")

      }

  }

  override func viewDidLoad() {
    super.viewDidLoad()
    collectionView?.backgroundColor = UIColor.white
    collectionView?.register(ItemCell.self, forCellWithReuseIdentifier: cellId)
    collectionView?.contentInset = UIEdgeInsetsMake(50, 0, self.view.frame.height, self.view.frame.width)
    collectionView?.scrollIndicatorInsets = UIEdgeInsetsMake(50, 0, 0, self.view.frame.width)
    collectionView?.dataSource = self
    collectionView?.delegate = self
    fetchData()
    DispatchQueue.main.async{self.collectionView?.reloadData()}
  }

  override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    print("in the method \(self.categories.count)")
    return self.categories.count
  }

  override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! ItemCell
    cell.category = categories[indexPath.item]
    return cell
  }

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: 111, height: 111)
  }

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 0
  }

  private func setupViweOptionBar() {
    view.addSubview(viewOptionVar)
    view.addConstraintsWithFormat(format: "H:|[v0]|", views: viewOptionVar)
    view.addConstraintsWithFormat(format: "V:|[v0(50)]", views: viewOptionVar)
  }
}

编辑2

以下代码是我的查询方法

func getAllCategory(username:String, password:String, callback: @escaping ([Category]?, String?) -> Void){
    var categories = [Category]()
    let fetchCategories = URL(string: userURL + "all")
    URLSession.shared.dataTask(with: fetchCategories!, completionHandler: { (data, response, error) in
        if let err = error {
            print(err)
            return
        }
        do {
            let jsonCategoryObj = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [[String: AnyObject]]
            for categoryDictionary in jsonCategoryObj {
                let category = Category()
                category.categoryId = categoryDictionary["categoryId"] as? String
                category.categoryName = categoryDictionary["categoryName"] as? String
                category.categoryDescription = categoryDictionary["categoryDescription"] as? String
                let categoryRegisteredDateString = categoryDictionary["categoryRegisteredDate"] as? String
                let df = DateFormatter()
                df.dateFormat = self.shapeDateFormat
                let categoryRegisteredDate = df.date(from: categoryRegisteredDateString!)!
                category.categoryRegisteredDate = categoryRegisteredDate

                categories.append(category)

            }
            callback(categories, nil)
        }catch let jsonError {
            callback(nil, String(describing: jsonError))
        }

    }).resume()
}

仅供参考:我知道我没有使用传递的用户凭证,它只是来自我的不同查询方法的复制和粘贴错误

3 个答案:

答案 0 :(得分:4)

我不确定这是如何解决这个问题的。但我刚刚补充

print("size of the array is \(self.categories?.count)")

就在

旁边
OperationQueue.main.addOperation{self.collectionView?.reloadData()}

它神奇地起作用..甚至当我回去并回到屏幕时,它没有显示任何内容。

我会对此进行更多调查,并尝试找出原因发生的原因

<强>更新

使用

DispatchQueue.main.sync

而不是

DispatchQueue.main.async

解决了这个问题。

答案 1 :(得分:1)

DispatchQueue.main.async{self.collectionView?.reloadData()}
    collectionView?.backgroundColor = UIColor.white
    collectionView?.register(ItemCell.self, forCellWithReuseIdentifier: cellId)

在您注册单元格之前,您正在重新加载数据。

注册您的单元格和数据源并首先委托方法,然后重新加载数据。

修改

我看到你编辑了你的帖子。

但是,在你注册牢房之前,你是fetchData()。因此,再次,在注册所有单元格,数据源和委托之后移动fetchData方法。

答案 2 :(得分:0)

当数据源更改时,reloadData不会更新视图中已显示的单元格。重新加载可见项目将完成这项工作。

    self.collectionView.reloadData()
    self.collectionView.performBatchUpdates({ [weak self] in
        let visibleItems = self?.collectionView.indexPathsForVisibleItems ?? []
        self?.collectionView.reloadItems(at: visibleItems)
    }, completion: { (_) in
    })