简体   繁体   English

UICollectionView reloadData 不起作用

[英]UICollectionView reloadData not working

Its getting called in viewDidLoad , after fetching the data used.在获取使用的数据后,它在viewDidLoad被调用。 After some print debugging it looks like it calls all the appropriate delegeate methods, if no data is changed.经过一些打印调试后,如果没有更改数据,它看起来会调用所有适当的委托方法。 If there has been some data changed, cellForItemAt does not get called.如果某些数据已更改,则不会调用cellForItemAt

Reloading the whole section works fine.重新加载整个部分工作正常。 But gives me an unwanted animation.但是给了我一个不需要的动画。 Tried disabling UIView animation before, and enabling after reloading section, but still gives me a little animation.之前尝试禁用UIView动画,并在重新加载部分后启用,但仍然给我一些动画。

collectionView.reloadSections(IndexSet(integer: 0)) 

Here is my current situation, when using reloadData()这是我目前的情况,使用 reloadData() 时

The UICollectionViewController is a part of a TabBarController. UICollectionViewController 是 TabBarController 的一部分。 I'm using custom UICollectionViewCells.我正在使用自定义 UICollectionViewCells。 The data is loaded from CoreData.数据从 CoreData 加载。

First time opening the tab, its works fine.第一次打开标签,它工作正常。 After updating the favorites item in another tab, and returning to this collectionView, its not updated.在另一个选项卡中更新收藏夹项后,返回到此 collectionView,它没有更新。 But if i select another tab, and go back to this one, its updated.但是如果我选择另一个选项卡,然后回到这个选项卡,它会更新。

var favorites = [Item]()


override func viewWillAppear(_ animated: Bool) {

    collectionView!.register(UINib.init(nibName: reuseIdentifier, bundle: nil), forCellWithReuseIdentifier: reuseIdentifier)

    if let flowLayout = collectionView!.collectionViewLayout as? UICollectionViewFlowLayout {
        flowLayout.estimatedItemSize = CGSize(width: 1,height: 1)
    }

    loadFavorites()

}


func loadFavorites() {

    do {
        print("Load Favorites")

        let fetch: NSFetchRequest = Item.fetchRequest()
        let predicate = NSPredicate(format: "favorite == %@", NSNumber(value: true))
        fetch.predicate = predicate
        favorites = try managedObjectContext.fetch(fetch)

        if favorites.count > 0 {
            print("Favorites count: \(favorites.count)")
            notification?.removeFromSuperview()
        } else {
            showEmptyFavoritesNotification()
        }

        print("Reload CollectionView")

        collectionView!.reloadData(


    } catch {
        print("Fetching Sections from Core Data failed")
    }
}


override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

    print("Get number of section, \(favorites.count)")
    if favorites.count > 0 {
        return favorites.count
    } else {
        return 0
    }
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    print("Get cell")

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! SubMenuCell

    let menuItem = favorites[indexPath.row]

    cell.title = menuItem.title
    cell.subtitle = menuItem.subtitle

    return cell
}

Console Print/Log控制台打印/日志

Starting the app, going to the CollectionView tab where there are no favorites:启动应用程序,转到没有收藏夹的 CollectionView 选项卡:

Load Favorites
Get number of section, 0
Get number of section, 0
Reload CollectionView
Get number of section, 0

Switching tab, and adding and setting an Item object's favorite to true, then heading back to the CollectionView tab:切换选项卡,添加 Item 对象的收藏夹并将其设置为 true,然后返回 CollectionView 选项卡:

Load Favorites
Favorites count: 1
Reload CollectionView
Get number of section, 1

The datamodel has 1 item, reloading CollectonView, cellForRowAtIndex not called?

Selecting another tab, random which, then heading back to the CollectionView tab, without changing any data.随机选择另一个选项卡,然后返回到 CollectionView 选项卡,而不更改任何数据。

Load Favorites
Favorites count: 1
Reload CollectionView
Get number of section, 1
Get cell

Now my Item shows up in the list.现在我的项目出现在列表中。 You can see from the Get Cell that cellForItemAt is called aswell.您可以从 Get Cell 中看到cellForItemAt也被调用。 Nothing has changed between these last two loggings, just clicked back/fourth on the tabs one time.这最后两次日志记录之间没有任何变化,只需在选项卡上单击后退/第四次。

Forgot to mention, but this code IS working fine in the simulator.忘了提,但这段代码在模拟器中运行良好。 On a read device its just not giving me any error, just not showing the cell (or calling the cellForItemAt )在读取设备上,它只是没有给我任何错误,只是没有显示单元格(或调用cellForItemAt

After some more debugging i got an error when the items got reduced (instead of increasing like i've tried above).经过更多调试后,当项目减少时出现错误(而不是像我上面尝试的那样增加)。

UICollectionView received layout attributes for a cell with an index path that does not exist

This led med to iOS 10 bug: UICollectionView received layout attributes for a cell with an index path that does not exist这导致了iOS 10 错误:UICollectionView 收到了具有不存在索引路径的单元格的布局属性

collectionView!.reloadData()
collectionView!.collectionViewLayout.invalidateLayout()
collectionView!.layoutSubviews()

This solved my problem.这解决了我的问题。

I am using autoresizing cells, but i guess this does not explain why cellForItemAt did not get called.我正在使用自动调整单元格,但我想这并不能解释为什么cellForItemAt没有被调用。

Ok, maybe I can help someone =)好的,也许我可以帮助某人 =)

I do this:我这样做:

  1. Load data from API从 API 加载数据
  2. Then after load data call DispatchQueue.main.async like this然后在加载数据后像这样调用 DispatchQueue.main.async

     DispatchQueue.main.async { self.pointNews = pointNews }
  3. In self.pointNews didSet I try to do collectionView.reloadData(), but it work only, if I call DispatchQueue.main.async in didSet在 self.pointNews didSet我尝试做 collectionView.reloadData(),但它只工作,如果我在 didSet 中调用 DispatchQueue.main.async

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

in my case, my collectionview was in a stackview, i didnt make any constraints, when i added the necessary constraints it worked.在我的例子中,我的 collectionview 在一个 stackview 中,当我添加必要的约束时,我没有做任何约束。

Just check collectionview's constraints.只需检查 collectionview 的约束。

var paths: [IndexPath] = []
if !data.isEmpty {
    for i in 0...salesArray.count - 1 {
        paths.append(IndexPath(item: i, section: 0))
    }
    collectionView.reloadData()
    collectionView.reloadItems(at: paths)
}

This is the code helped me, for solving this kind of issue.这是帮助我解决此类问题的代码。

Post your code.发布您的代码。

One possibility is that you are using `URLSession and trying to tell your collection view to update from the it's delegate method/completion closure, not realizing that that code is run on a background thread and you can't do UI calls from background threads.一种可能性是您正在使用 `URLSession 并试图告诉您的集合视图从它的委托方法/完成闭包更新,没有意识到该代码在后台线程上运行并且您不能从后台线程进行 UI 调用。

I faced the same problem with self resizing cells and above solution works as well but collection view scroll position resets and goes to top.我遇到了与自我调整单元格大小相同的问题,上述解决方案也有效,但集合视图滚动位置重置并转到顶部。 Below solution helps to retain your scroll position .以下解决方案有助于保留您的滚动位置

collectionView.reloadData()
let context = collectionView.collectionViewLayout.invalidationContext(forBoundsChange: collectionView.bounds)
context.contentOffsetAdjustment = CGPoint.zero
collectionView.collectionViewLayout.invalidateLayout(with: context)
collectionView.layoutSubviews()

i was facing also this kind of issue so finally i am able to solved using this line of code我也面临这种问题,所以最后我能够使用这行代码解决

[self.collectionView reloadData]; [self.collectionView reloadData];

[self.collectionView reloadItemsAtIndexPaths:@[[NSIndexPath indexPathWithIndex:0]]]; [self.collectionView reloadItemsAtIndexPaths:@[[NSIndexPath indexPathWithIndex:0]]];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM