菜鸟教程小白 发表于 2022-12-12 23:33:52

ios - Realm Swift 使用部分更新 collectionView


                                            <p><p>我有一个刚刚添加了部分的 collectionView,我正在使用 RealmSwift。在添加这些部分之前,我能够对数据进行更改并在我的 collectionView 中查看它们的更新/删除。</p>

<p>我关注了<a href="https://realm.io/docs/swift/latest/api/Enums/RealmCollectionChange.html" rel="noreferrer noopener nofollow">docs</a>添加通知,以便我的结果对象中的更改将触发 UI 更改;请注意,我对我的 collectionView 进行了适当的更改。</p>

<pre><code>func notificationSubscription(for outfits: Results&lt;Outfit&gt;) -&gt; NotificationToken {
    return outfits.addNotificationBlock({ (changes: RealmCollectionChange&lt;Results&lt;Outfit&gt;&gt;) in
      self?.updateUI(with: changes)
    })
}

func updateUI(with changes: RealmCollectionChange&lt;Results&lt;Outfit&gt;&gt;) {
    switch changes {
    case .initial(_):
      collectionView.reloadData()
    case let .update(_, deletions, insertions, modifications):
      collectionView.performBatchUpdates({
            self.collectionView.reloadItems(at: modifications.map { IndexPath(row: $0, section: 0) })
            self.collectionView.insertItems(at: insertions.map { IndexPath(row: $0, section: 0) })
            self.collectionView.deleteItems(at: deletions.map { IndexPath(row: $0, section: 0) })
      }, completion: { (completed: Bool) in
            self.collectionView.reloadData()
      })
      break
    case let .error(error):
      print(error.localizedDescription)
    }
}
</code></pre>

<p>我很清楚 <code>updateUI(with: changes)</code> 中的问题是 IndexPaths 被硬编码为第 0 节。当我编辑一个项目时,我的应用程序因此崩溃,所以我搜索周围遇到了<a href="https://github.com/realm/realm-cocoa/issues/4186#issuecomment-261458292" rel="noreferrer noopener nofollow">this</a> GitHub上的问题。 Pawelkata(评论员)提到,该问题的快速修复(现已关闭)是在 switch 语句的 <code>update</code> 案例中调用 <code>collectionView.reloadData()</code>。</code> p>

<pre><code>func updateUI(with changes: RealmCollectionChange&lt;Results&lt;Outfit&gt;&gt;) {
    switch changes {
    case .initial(_):
      collectionView.reloadData()
    case let .update(_, deletions, insertions, modifications):
      collectionView.reloadData()
      break
    case let .error(error):
      print(error.localizedDescription)
    }
}
</code></pre>

<p>虽然快速修复适用于修改和插入,但在删除的情况下会失败。这是因为新数据是在其他地方添加/修改的,但删除发生在同一个 viewController 上,因此这些更改实际上不会更新 UI。</p>

<p>我找到了 <a href="https://stackoverflow.com/a/38797693/2892925" rel="noreferrer noopener nofollow">this</a>密切相关的 stackoverflow 问题,@jpsim 回答了某人关于在 tableView 中有多个部分的问题。在@MikePollard 的评论中询问是否可以将带有多个部分的 tableView 与 Realm 集合通知结合起来。 JPSim 说这很棘手,但有可能。虽然我有一个 collectionView 而不是 tableView 我假设这也是可能的。</p>

<p>我尝试过的:</p>

<ol>
<li><p>因为我需要知道项目来自哪个部分,所以我创建了一个变量来存储所选项目的 indexPath。
<code>var indexPathForDeletion = IndexPath()</code></p>

<p>然后我在 <code>didSelectItem</code> 中设置,并在 <code>updateUI(with: changes)</code> 中使用。</p>

<pre><code>func updateUI(with changes: RealmCollectionChange&lt;Results&lt;Outfit&gt;&gt;) {
    switch changes {
    case .initial(_):
      collectionView.reloadData()
    case let .update(_, deletions, insertions, modifications):
      collectionView.performBatchUpdates({
            self.collectionView.deleteItems(at: )
      }, completion: { (completed: Bool) in
            self.collectionView.reloadData()
      })
      break
    case let .error(error):
      print(error.localizedDescription)
    }
}
</code></pre>

<p>应用程序由于未捕获的异常“NSInternalInconsistencyException”而崩溃,<code>终止应用程序,原因:“无效更新:第 2 节中的项目数无效。更新后现有节中包含的项目数 (2) 必须等于更新前该节中包含的项目数 (2),加上或减去从该节插入或删除的项目数(0 插入,1 删除),加上或减去移入或移出的项目数该部分的内容(0 移入,0 移出)。'</code></p>

<p>我从 2 个项目开始,我删除了 1 个项目,我应该还剩下 1 个项目,但似乎我还有 2 个。这是我对错误的解释。我的解释正确吗?为什么不删除项目?</p></li>
<li><p>我有一个哈希表来存储这些部分,它是结果数组,所以我创建了一个函数来更新哈希表,然后重新加载 collectionView。</p>

<pre><code>func refreshData() {
    getOutfitsByCategory()
    collectionView.reloadData()
}

func getOutfitsByCategory() {
    for category in categories {
      outfitsByCategory = outfits.filter(&#34;category = %@&#34;, category)
    }
}
</code></pre>

<p>这给了我一个“更好”的结果,但似乎有些奇怪。我可以删除它们在索引 0 处的项目 <em>iff</em>,无论部分如何。但是,删除索引 0 处的项目将删除它所在的整个部分。</p></li>
</ol>

<p>我错过了什么?</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>根据您的 Collection View 有多少个部分,为每个部分的每组结果简单地设置一个单独的通知 block 可能会更容易。这需要为每个部分(以及随后的通知 token )维护一个单独的 <code>Results</code> 对象,因此根据您拥有的部分的数量,此解决方案可能会有些复杂。</p>

<p>另一个考虑可能是试用 <a href="https://github.com/Roobiq/RBQFetchedResultsController" rel="noreferrer noopener nofollow"><code>RBQFetchedResultsController</code></a> .这是在 Realm 中可用更改通知之前构建的 Controller (作为 Realm 员工的第三方项目),因此虽然它不像主集合通知系统那样“原生”,但它也可以解释表/ Collection View 部分。 </p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - Realm Swift 使用部分更新 collectionView,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/41535521/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/41535521/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - Realm Swift 使用部分更新 collectionView