更新嵌套的 UICollectionView - Swift 3

Posted

技术标签:

【中文标题】更新嵌套的 UICollectionView - Swift 3【英文标题】:Updating nested UICollectionView - Swift 3 【发布时间】:2017-04-15 10:49:19 【问题描述】:

我在更新 UICollectionView 时遇到问题。我有以下设置,其中包含嵌套的 collectionView。

homeControllerView 是具有 CollectionView 1 的 collectionViewController,启用了分页。 CollectionView 1 的每个单元格本身就是一个 collectionView,例如CollectionView A, B, ... 这样做的原因是,每个 CollectionView A, B, ... 都是一个提要,它获取信息,然后显示为单元格 A1、A2、B1 ...

加载 HomeViewController 时,所有 CollectionViews A、B ... 都已填充,每个 (Main)Cell 1、2 将开始获取信息。一些提要正在获取绑定到当前登录用户的个人信息。

切换到另一个用户后,我想让 (Main)collectionView 更新,以便所有 Cell 1、2、... 都盯着再次获取信息。所以在我的 LoginController 中我调用了

self.homeController?.collectionView?.reloadData()

但这似乎只适用于当前可见的单元格,例如显示示例中的单元格 2。此外,重新加载项目仅适用于可见的项目:

self.homeController?.collectionView?.reloadItems(at: (self.homeController?.collectionView?.indexPathsForVisibleItems)!)

在我的 homeViewController 中,我像这样覆盖 cellForItem 函数

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
    switch indexPath.item 
        case 0:
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: incomingFeedCellId, for: indexPath) as! IncomingFeedCell
            return cell
        case 1:
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: popularFeedCellId, for: indexPath) as! PopularFeedCell
            return cell
        case 2:
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: favoritFeedCellId, for: indexPath) as! FavoritFeedCell
            return cell
        case 3:
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: personalFeedCellId, for: indexPath) as! PersonalFeedCell
            return cell
        default:
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: incomingFeedCellId, for: indexPath) as! IncomingFeedCell
            return cell
    

但是.reloadData() 不会再次调用 cellForItem 函数,因此一旦启动,单元格将不会再次更新。

每个 FeedCell 都有一个 fetch() 函数,至少在创建单元格后调用该函数:

func fetch()
    posts = [Post]()
    let ref = FIRDatabase.database().reference()

    ref.child("posts_incoming").queryOrderedByKey().observe(.childAdded, with:  (snapshot) in
        if let dictionary = snapshot.value as? NSDictionary 
            let post = Post()
            post.imageUrl = dictionary["image_url"] as? String
            post.caption = dictionary["caption"] as? String
            ...
            ...
            self.posts?.append(post)

            DispatchQueue.main.async(execute: 
                self.collectionView.reloadData()
            )
        
    , withCancel: nil)

目前我在 (Main)Cells 中跟踪 userId,因此,当 Cell 出列时(例如,滑动到下一个提要),它会检查 uid 是否已更改,如果是,则将再次执行 fetch。 ..但我确信对于这个问题必须是一个更优雅的解决方案。有没有办法丢弃所有单元格并为每个单元格强制进行新的初始化?

【问题讨论】:

【参考方案1】:

我建议创建UICollectionView 的自定义类,并且所有提要获取调用都应在自定义UICollectionView 类中进行。 也为了保持简单,比如不嵌套UICollectionViews,你可以使用:

用于分页的主 UICollectionView 并在 UICollectionView 的单元格内添加 UITableview。

所以重新加载会是这样的:

UIViewController 中的 UICollectionView

UICollectionView自定义类中的UITableview

此外,您必须始终使用dequeueReusableCell,否则将分配过多内存,导致您的应用崩溃。

【讨论】:

感谢您的回答,但我不明白这有什么帮助。如果我将 CollectionView 1 创建为自定义 CollectionView 并使用一个新函数来更新单元格,我仍然无法访问那些不可见的单元格,对吧? 是的,如果你固定了 5 个超级单元格,你可以做一件事,用户 ScrollView,其内容大小是视图的 5 倍。然后在每个 containerView 中添加 5 个包含分离 UIViewControllers 的容器视图。这样您就可以轻松管理一切。

以上是关于更新嵌套的 UICollectionView - Swift 3的主要内容,如果未能解决你的问题,请参考以下文章

嵌套垂直 UICollectionView 和动态高度

多层ScrollView嵌套UITableView、UICollectionView联动

UITableViewCell中嵌套UICollectionView

嵌套的 UICollectionView 为每个部分返回相同的值 - Swift

iOS 7.1 在 UIPopover 中嵌套 UICollectionView

以编程方式将 UICollectionView 嵌套在 UIVIew 中