Firebase Swift - 当搜索控制器过滤结果时,实时更新不起作用
Posted
技术标签:
【中文标题】Firebase Swift - 当搜索控制器过滤结果时,实时更新不起作用【英文标题】:Firebase Swift - Realtime update does not work when result is filtered by search controller 【发布时间】:2018-04-23 13:22:08 【问题描述】:我正在使用 Swift 和 Firebase 制作 ios 应用。视图控制器检索/观察项目并将它们存储在项目数组中。项目单元格具有 + 和 - 按钮,它们使用其 indexPath 执行项目数量的更新。
如果我使用搜索控制器过滤项目,我可以将搜索结果存储在 filtersItems 数组中。我正在尝试更新这些过滤项目的数量,但是当我点击 + 或 - 按钮时它们只会更新一次,并且不会在搜索结果视图中显示更新(没有单独的视图,我在同一视图中使用数据源显示过滤的项目)。即使我多次点击它,它也总是更新一次。
一旦我通过取消搜索栏返回常规视图,我看到 1 向上或向下取决于我点击的按钮。有谁知道这里的问题可能是什么原因?
class ItemsViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, SortTypeTableViewControllerDelegate, ItemListCellDelegate
private var items = [Item]()
private var filteredItems = [Item]()
private func retrieveFirebaseData(sortType: ItemSort.SortType, sortOrder: ItemSort.SortOrder)
guard let currentUser = Auth.auth().currentUser else
return print("user not logged in")
let itemsRef = DatabaseReferenceHelper.usersRef.child(currentUser.uid).child("items")
itemsRef.queryOrdered(byChild: sortType.rawValue).observe(.value) (snapshot) in
var newItems: [Item] = []
for item in snapshot.children
let item = Item(snapshot: item as! DataSnapshot)
if self.displayFavoritesOnly == true
if item.favorite == true
newItems.append(item)
else
newItems.append(item)
self.items = sortOrder == .ascending ? newItems : newItems.reversed()
self.collectionView.reloadData()
// this is from item cell delegate
func increaseDecreaseQuantity(_ sender: ItemListCell, increment: Bool)
guard let tappedIndexPath = collectionView.indexPath(for: sender) else
return
let item: Item
item = isFiltering() ? filteredItems[tappedIndexPath.item] : items[tappedIndexPath.item]
let updatedQuantity = increment == true ? item.quantity + 1 : item.quantity - 1
guard let currentUser = Auth.auth().currentUser else
return print("user not logged in")
let itemsRef = DatabaseReferenceHelper.usersRef.child(currentUser.uid).child("items")
itemsRef.child(item.key).updateChildValues(["quantity": updatedQuantity])
// Here's the search logic I learned from Ray Wenderlich
private func searchBarIsEmpty() -> Bool
return searchController.searchBar.text?.isEmpty ?? true
private func filterContentForSearchText(_ searchText: String, scope: String = "All")
filteredItems = items.filter($0.title.lowercased().contains(searchText.lowercased()))
collectionView.reloadData()
private func isFiltering() -> Bool
return searchController.isActive && !searchBarIsEmpty()
extension ItemsViewController: UISearchResultsUpdating
func updateSearchResults(for searchController: UISearchController)
filterContentForSearchText(searchController.searchBar.text!)
【问题讨论】:
使用此代码,每次更新特定项目时,都会重新加载整个项目列表。另一种选择是使用 .childAdded、.childChanged 和 .childRemoved,因此当仅修改一项时,您可以只更新数组中的一项。 @Jay 这是提高代码效率的建议还是可能的修复?我看到一篇博文说 .childAdded、.childChanged、.childRemoved 的具体用法可以保存数据,所以我也想使用它们。 这更像是一个建议,可以让它更干净一些,并减少对 Firebase 的命中和移动的数据量。我没有看到任何会导致您描述的问题的明显代码问题。 【参考方案1】:在每个 + & - 之后重新加载您的 collectionView。重新加载集合视图后,将显示新的更新。
【讨论】:
我试过了,但它什么也没做。另外,当结果未被过滤时,我不需要重新加载集合视图来实时更新我的数据。【参考方案2】:我解决了这个问题。我所做的只是在retrieveFirebaseData 函数中添加另一个名为“searchText”的参数,并在filterContentForSearchText 中使用该函数。
基本上,我需要像下面的代码一样在观察方法下过滤项目。
private func retrieveFirebaseData(sortType: ItemSort.SortType, sortOrder: ItemSort.SortOrder, searchText: String?)
guard let currentUser = Auth.auth().currentUser else
return print("user not logged in")
let itemsRef = DatabaseReferenceHelper.usersRef.child(currentUser.uid).child("items")
itemsRef.queryOrdered(byChild: sortType.rawValue).observe(.value) (snapshot) in
if let searchText = searchText
// FILTER HERE
self.filteredItems = self.items.filter($0.title.lowercased().contains(searchText.lowercased()))
else
var newItems: [Item] = []
for item in snapshot.children
let item = Item(snapshot: item as! DataSnapshot)
if self.displayFavoritesOnly == true
if item.favorite == true
newItems.append(item)
else
newItems.append(item)
self.items = sortOrder == .ascending ? newItems : newItems.reversed()
self.collectionView.reloadData()
private func filterContentForSearchText(_ searchText: String, scope: String = "All")
retrieveFirebaseData(sortType: itemSortType, sortOrder: itemSortOrder, searchText: searchText)
“filterContentForSearchText”函数用于过滤项目并重新加载表格,如下所示:
private func filterContentForSearchText(_ searchText: String, scope: String = "All")
filteredItems = items.filter($0.title.lowercased().contains(searchText.lowercased()))
collectionView.reloadData()
【讨论】:
以上是关于Firebase Swift - 当搜索控制器过滤结果时,实时更新不起作用的主要内容,如果未能解决你的问题,请参考以下文章
Firebase - 为啥不搜索在我的应用中工作的用户? (当用户输入两个字母时更新搜索控制器)