Firebase Swift - 当搜索控制器过滤结果时,实时更新不起作用
Firebase Swift - Realtime update does not work when result is filtered by search controller
我正在使用 Swift 和 Firebase 制作一个 iOS 应用程序。视图控制器 retrieves/observes 项目并将它们存储在项目数组中。项目单元格具有 + 和 - 按钮,可使用其索引路径对项目数量执行更新。
如果我使用搜索控制器来过滤项目,我可以将搜索结果存储在 filteredItems 数组中。我正在尝试更新这些过滤项目的数量,但当我点击 + 或 - 按钮时它们只会更新一次,并且不会在搜索结果视图中显示更新(没有单独的视图,我在同一视图中使用数据源显示过滤项目).就算我打了很多次,它也总是更新一次。
通过取消搜索栏返回常规视图后,我看到向上或向下 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({[=11=].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!)
}
}
在每次 + & - 后重新加载您的 collectionView。重新加载 collection 视图后,将显示新的更新。
我解决了这个问题。我所做的只是在 retrieveFirebaseData 函数中添加另一个名为 "searchText" 的参数,并在 filterContentForSearchText.
中使用该函数
基本上,我需要像下面的代码一样在 observe 方法下过滤项目。
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({[=10=].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" 函数用于过滤项目和重新加载 table 像这样:
private func filterContentForSearchText(_ searchText: String, scope: String = "All") {
filteredItems = items.filter({[=11=].title.lowercased().contains(searchText.lowercased())})
collectionView.reloadData()
}
我正在使用 Swift 和 Firebase 制作一个 iOS 应用程序。视图控制器 retrieves/observes 项目并将它们存储在项目数组中。项目单元格具有 + 和 - 按钮,可使用其索引路径对项目数量执行更新。
如果我使用搜索控制器来过滤项目,我可以将搜索结果存储在 filteredItems 数组中。我正在尝试更新这些过滤项目的数量,但当我点击 + 或 - 按钮时它们只会更新一次,并且不会在搜索结果视图中显示更新(没有单独的视图,我在同一视图中使用数据源显示过滤项目).就算我打了很多次,它也总是更新一次。
通过取消搜索栏返回常规视图后,我看到向上或向下 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({[=11=].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!)
}
}
在每次 + & - 后重新加载您的 collectionView。重新加载 collection 视图后,将显示新的更新。
我解决了这个问题。我所做的只是在 retrieveFirebaseData 函数中添加另一个名为 "searchText" 的参数,并在 filterContentForSearchText.
中使用该函数基本上,我需要像下面的代码一样在 observe 方法下过滤项目。
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({[=10=].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" 函数用于过滤项目和重新加载 table 像这样:
private func filterContentForSearchText(_ searchText: String, scope: String = "All") {
filteredItems = items.filter({[=11=].title.lowercased().contains(searchText.lowercased())})
collectionView.reloadData()
}