Мое приложение позволяет пользователям продавать такие вещи, как кроссовки и т. Д. Кроссовки, которые отображаются в ленте пользователя, основаны на продавцах, которые разместили товары, которые находятся рядом с пользователем.Я использую GeoFire, чтобы узнать местоположение продавца, и все работает отлично.Когда пользователь использует pullToRefresh, если рядом нет новых данных / кроссовок, тогда нет необходимости обновлять список.
Место, где я в тупике, - это когда пользователь вытягивает PullToRefresh.Как определить, что новые товары были добавлены либо совершенно новым продавцом, который находится рядом, либо тем же продавцом, который добавил дополнительные пары кроссовок?
Например,Пользователь А живет в почтовом индексе 10463, и в радиусе 20 миль находятся 2 продавца.Любые кроссовки, которые эти продавцы выставят на продажу, появятся в ленте пользователя.Но третий продавец может прийти и выложить пару кроссовок, или любой из первых 2 продавцов может добавить дополнительную пару.Если пользователь pullsToRefesh, то эти элементы появятся, но если ничего не будет добавлено, то pullToRefresh не должен ничего делать.
Я не хочу излишне перезапускать код firebase, если мне это не нужно.Единственный способ сделать это - сначала проверить postsRef, чтобы проверить, были ли добавлены новые кроссовки двумя продавцами или совершенно новым продавцом, который также находится поблизости.
код:
let refreshControl: UIRefreshControl = {
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(pullToRefresh), for: .valueChanged)
return refreshControl
}()
@objc func pullToRefresh() {
// if there aren't any new nearby sellers or current sellers with new items then the two lines below shouldn't run
arrOfPosts.removeAll() // this is the array that has the collectionView's data. It gets populated in thirdFetchPosts()
firstGetSellersInRadius(miles: 20.0)
}
override func viewDidLoad() {
super.viewDidLoad()
firstGetSellersInRadius(miles: 20.0) // the user can change the mileage but it's hardcoded for this example
}
// 1. I get the user's location and then get all the nearby sellers
func firstGetSellersInRadius(miles: Double) {
// user's location
guard let currentLocation = locationManager.location else { return }
let lat = currentLocation.coordinate.latitude
let lon = currentLocation.coordinate.longitude
let location = CLLocation(latitude: lat, longitude: lon)
let radiusInMeters = (miles * 2) * 1609.344 // 1 mile == 1609.344 meters
let region = MKCoordinateRegion(center: location.coordinate, latitudinalMeters: radiusInMeters, longitudinalMeters: radiusInMeters)
let geoFireRef = Database.database().reference().child("geoFire")
regionQuery = geoFireRef?.query(with: region)
queryHandle = regionQuery?.observe(.keyEntered, with: { (key: String!, location: CLLocation!) in
let geoModel = GeoModel()
geoModel.userId = key
geoModel.location = location
self.arrOfNearbySellers.append(geoModel)
})
regionQuery?.observeReady({
self.secondLoopNearbySellersAndGetTheirAddress(self.arrOfNearbySellers)
})
}
// 2. I have to grab the seller's username and profilePic before I show their posts because they're shown along with the post
func secondLoopNearbySellersAndGetTheirAddress(_ geoModels: [GeoModel]) {
let dispatchGroup = DispatchGroup()
for geoModel in geoModels {
dispatchGroup.enter()
if let userId = geoModel.userId {
let uidRef = Database.database().reference().child("users")?.child(userId)
uidRef.observeSingleEvent(of: .value, with: { [weak self](snapshot) in
guard let dict = snapshot.value as? [String: Any] else { dispatchGroup.leave(); return }
let profilePicUrl = dict["profilePicUrl"] as? String
let username = dict["username"] as? String
let userModel = UserModel()
userModel.profilePicUrl = profilePicUrl
userModel.username = username
self?.arrOfSellers.append(userModel)
dispatchGroup.leave()
})
}
}
dispatchGroup.notify(queue: .global(qos: .background)) { [weak self] in
self?.thirdFetchPosts(self!.arrOfSellers)
}
}
// 3. now that I have their address I fetch their posts
func thirdFetchPosts(_ userModels: [UserModel]) {
let dispatchGroup = DispatchGroup()
var postCount = 0
var loopCount = 0
for userModel in userModels {
dispatchGroup.enter()
if let userId = userModel.userId {
let postsRef = Database.database().reference().child("posts")?.child(userId)
postsRef?.observe( .value, with: { [weak self](snapshot) in
postCount = Int(snapshot.childrenCount)
guard let dictionaries = snapshot.value as? [String: Any] else { dispatchGroup.leave(); return }
dictionaries.forEach({ [weak self] (key, value) in
print(key, value)
loopCount += 1
guard let dict = value as? [String: Any] else { return }
let postModel = PostModel(userModel: userModel, dict: dict)
self?.arrOfPosts.append(postModel)
if postCount == loopCount {
dispatchGroup.leave()
postCount = 0
loopCount = 0
}
})
})
}
}
dispatchGroup.notify(queue: .global(qos: .background)) { [weak self] in
self?.fourthRemoveQueryObserverReloadCollectionView()
}
}
// 4. now that I have all the posts inside the arrOfPosts I can show them in the collectionView
func foutrhRemoveQueryObserverReloadCollectionView() {
DispatchQueue.main.async { [weak self] in
self?.arrOfPosts.sort { $0.postDate ?? 0 > $1.postDate ?? 0}
self?.refreshControl.endRefreshing()
if let queryHandle = self?.queryHandle {
self.regionQuery?.removeObserver(withFirebaseHandle: queryHandle)
}
self?.collectionView.reloadData()
self?.arrOfNearbySellers.removeAll()
self?.arrOfSellers.removeAll()
}
}