小分页问题

好的,我有一个小的分页问题。 我的代码根据密钥从我的firebase数据库中提取信息。 让MIA成为关键。 如果我想加载信息,我所要做的就是转到该键并获取信息。 所以我的分页方法根据键一次加载4个东西。

这是我在firebase中的树的片段,它按位置收集密钥,然后根据我的获取方法从另一棵树中提取信息。 其中列出如下。 正如大家所知,分页加载小块数据而不是一次性加载数据。 我的帮助函数通过加载前四个然后保存第四个键以启动另一个分页请求以加载接下来的四个来完成该任务。

在前四个加载之后,我滚动它会激活我的分页以加载接下来的四个。 那时的当前关键是MIA3应该是什么,因为这是最后加载的东西。

问题是它从来没有抓住密钥DD从firebase加载下一组数据,我不知道为什么。 也许是因为它还需要加载四个? 我怀疑事情不会加载,除非有额外的四个,而不是我的整个数据库必须以四的倍数为中心,我不认为分页是这样的。 简而言之,为什么我的程序永远不会获取第五个键来加载我的数据库中的最后一个东西? 这真让我烦恼

eventsbylocation" : { "37%2e7,-122%2e4" : { "event0" : "MIA", "event1" : "CCDS", "event2" : "MIA2", "event3" : "MIA3", "event4" : "DD" }, "40%2e7,-74%2e0" : { "event" : "DD" } }, 

它从此树中提取与密钥相关的信息

 "events" : { "CCDS" : { "attend:count" : 2, "event:category" : "Seize The Day", "event:city" : "San Francisco", "event:date" : { "end:date" : "08/09/2017", "end:time" : "7:00 PM", "start:date" : "08/09/2017", "start:time" : "5:00 PM" }, "event:description" : "Happy hour is more joyful in the summer thanks to Center City District Sips, which offers discounted drinks and appetizers every Wednesday evening. Catch up with old friends and make a few new ones as Center City's best bars and restaurants host the summer's happiest hour every Wednesday from 5-7 pm Enjoy $5 cocktails, $4 wine, $3 beers and half-price appetizers at dozens and dozens of bars and restaurants.", "event:imageURL" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/event_flyers%2FCCDS-compressor.jpg?alt=media&token=bcce3968-1cca-4890-a3d0-d8064bd0d1da", "event:name" : "center city district sips", "event:promo" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/event_promo_vid%2FMIA%2FBudweiser%20Made%20In%20America%20Festival%202013%20August%2031%20-%20September%201.mp4?alt=media&token=9b4b9d4f-2d6d-4762-a5fd-c72edb943ac4", "event:state" : "PA", "event:street:address" : "660 Chestnut St", "event:zip" : 19130 }, "DD" : { "attend:count" : 2, "event:category" : "I Love College", "event:city" : "New York", "event:date" : { "end:date" : "08/26/2017", "end:time" : "5:00 PM", "start:date" : "08/26/2017", "start:time" : "1:00 PM" }, "event:description" : "Help us celebrate the hard work and creativity of the students and demo the iOS apps and games they've built in only 8 weeks! Developers, entrepreneurs, friends, and industry professionals are all welcome to attend", "event:imageURL" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/event_flyers%2Fmakeschooldemo-compressor.jpg?alt=media&token=1e75d18d-1949-48e8-a208-2ca88cde395b", "event:name" : "demo day", "event:promo" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/event_promo_vid%2FDD%2FDemo%20Night%202017%20-%20Make%20School%20Product%20College.mp4?alt=media&token=d9adb4b1-5689-4b15-96b2-e18138701526", "event:state" : "PA", "event:street:address" : "394 Broadway", "event:zip" : 10013 }, "MIA" : { "attend:count" : 23, "event:category" : "Seize The Night", "event:city" : "San Francisco", "event:date" : { "end:date" : "09/03/2017", "end:time" : "7:00 PM", "start:date" : "09/02/2017", "start:time" : "12:00 PM" }, "event:description" : "Budweiser Made in America Festival is an annual music festival held in Philadelphia and formerly simultaneously held in Los Angeles.Sponsored by Anheuser–Busch and produced by Live Nation, the event features several stages that continuously host live music from a wide range of genres including hip hop, rock, pop, R&B, and EDM.", "event:imageURL" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/event_flyers%2FMadeInAmerica-compressor.jpg?alt=media&token=1ac6e794-6a1f-4f8a-bdb0-afc91f8ba6ae", "event:name" : "made in america", "event:promo" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/event_promo_vid%2FMIA%2FBudweiser%20Made%20In%20America%20Festival%202013%20August%2031%20-%20September%201.mp4?alt=media&token=11e5059f-3973-4a74-9c9b-a537b737e0ab", "event:state" : "PA", "event:street:address" : "Ben Franklin Parkway", "event:zip" : 19130 }, "MIA2" : { "attend:count" : 2, "event:category" : "Dress To Impress", "event:city" : "Philadelphia", "event:date" : { "end:date" : "09/03/2017", "end:time" : "7:00 PM", "start:date" : "09/02/2017", "start:time" : "12:00 PM" }, "event:description" : "Budweiser Made in America Festival is an annual music festival held in Philadelphia and formerly simultaneously held in Los Angeles. Sponsored by Anheuser–Busch and produced by Live Nation, the event features several stages that continuously host live music from a wide range of genres including hip hop, rock, pop, R&B, and EDM. This is different regardless of the same name in database", "event:imageURL" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/event_flyers%2Fmadeinamerica2.jpg?alt=media&token=bd5eb5e4-4e22-4412-a34b-2dc6c9ae561e", "event:name" : "made in america", "event:promo" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/event_promo_vid%2FMIA%2FBudweiser%20Made%20In%20America%20Festival%202013%20August%2031%20-%20September%201.mp4?alt=media&token=11e5059f-3973-4a74-9c9b-a537b737e0ab", "event:state" : "PA", "event:street:address" : "Ben Franklin Parkway", "event:zip" : 19130 }, "MIA3" : { "attend:count" : 8, "event:category" : "21 & Up", "event:city" : "Philadelphia", "event:date" : { "end:date" : "09/03/2017", "end:time" : "7:00 PM", "start:date" : "09/02/2017", "start:time" : "12:00 PM" }, "event:description" : "Budweiser Made in America Festival is an annual music festival held in Philadelphia and formerly simultaneously held in Los Angeles. Sponsored by Anheuser–Busch and produced by Live Nation, the event features several stages that continuously host live music from a wide range of genres including hip hop, rock, pop, R&B, and EDM.", "event:imageURL" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/event_flyers%2Fmadeinamerica3-compressor.jpg?alt=media&token=9166e2fb-ac9d-46d5-b06f-60cffc337b15", "event:name" : "made in america", "event:promo" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/event_promo_vid%2FMIA%2FBudweiser%20Made%20In%20America%20Festival%202013%20August%2031%20-%20September%201.mp4?alt=media&token=11e5059f-3973-4a74-9c9b-a537b737e0ab", "event:state" : "PA", "event:street:address" : "Ben Franklin Parkway", "event:zip" : 19130 } } 

我的分页是通过这种辅助方法完成的

 protocol Keyed { var key: String? { get set } } // Create a new instance using a genetic type //let paginationHelper = MGPaginationHelper() // Generic class type // 1. initial - no data has been loaded yet // 2. ready - ready and waiting for next request to paginate and load the next page // 3. loading - currently paginating and waiting for data from Firebase // 4. end - all data has been paginated enum PaginationState { case initial case ready case loading case end } class PaginationHelper { // MARK: - Properties // 1. page size - Determines the number of posts that will be on each page // 2. serviceMethod - The service method that will return paginated data // 3. state - The current pagination state of the helper // 4. lastobjectKey - Firebase uses object keys to determine the last position of the page. We'lll need to use this as an offset for paginating. let pageSize: UInt let serviceMethod: (UInt, String?,String?, @escaping (([T]) -> Void)) -> Void var state: PaginationState = .initial var lastObjectKey: String? var category: String? // MARK: - Init // Can change the default page size for our helper // Set the service method that will be paginated and return data init(pageSize: UInt = 4, serviceMethod: @escaping (UInt, String?,String?, @escaping (([T]) -> Void)) -> Void) { self.pageSize = pageSize self.serviceMethod = serviceMethod } // 1 Notice our completion parameter type. We use our generic type to enforce that we return type T. func paginate(completion: @escaping([T]) -> Void) { // 2 We switch on our helper's state to determine the behavior of our helper when paginate(completion:) is called switch state { // 3 For our initial state, we make sure that the lastObjectKey is nil use the fallthrough keyword to execute the ready case below. case .initial: lastObjectKey = nil fallthrough //4 For our ready state, we make sure to change the state to loading and execute our service method to return the paginated data. case .ready: state = .loading // print(lastObjectKey) serviceMethod(pageSize, lastObjectKey, category) { [unowned self] (objects: [T]) in //5 We use the defer keyword to make sure the following code is executed whenever the closure returns. This is helpful for removing duplicate code. defer { //6 If the returned last returned object has a key value, we store that in lastObjectKey to use as a future offset for paginating. Right now the compiler will throw an error because it cannot infer that T has a property of key. We'll fix that next. if let lastObjectKey = objects.last?.key { self.lastObjectKey = lastObjectKey // print(self.lastObjectKey) // print(lastObjectKey) } // 7 We determine if we've paginated through all content because if the number of objects returned is less than the page size, we know that we're only the last page of objects. self.state = objects.count  Void) { state = .initial paginate(completion: completion) } } 

哪个叫这个function

 import Foundation import UIKit import Firebase struct PostService { static func create(for event: String?,for vidURL: String) { // 1 guard let key = event else { return } let storyUrl = vidURL // 2 guard let uid = Auth.auth().currentUser?.uid else{ return } let story = Story(url: storyUrl) let dict = story.dictValue let postRef = Database.database().reference().child("Stories").child(key).childByAutoId() let userRef = Database.database().reference().child("users").child(uid).child("Stories").child(key).childByAutoId() postRef.updateChildValues(dict) userRef.updateChildValues(dict) } static func showEvent(pageSize: UInt, lastPostKey: String? = nil, category: String? = nil,completion: @escaping ([Event]) -> Void) { //getting firebase root directory // print(lastPostKey) // print("came here") var currentEvents = [Event]() let eventsByLocationRef = Database.database().reference().child("eventsbylocation").child(User.current.location!) //let ref = Database.database().reference().child("events") var query = eventsByLocationRef.queryOrderedByKey().queryLimited(toFirst: pageSize) if let lastPostKey = lastPostKey { // print(lastPostKey) query = query.queryEnding(atValue: lastPostKey) } query.observeSingleEvent(of: .value, with: { (snapshot) in // print(snapshot) // print(snapshot.value) guard let allObjects = snapshot.children.allObjects as? [DataSnapshot] else{ return } allObjects.forEach({ (snapshot) in // print(snapshot.value ?? "") print(category) EventService.show(forEventKey: snapshot.value as! String,eventCategory: category, completion: { (event) in currentEvents.append(event!) // print("\n\n\n\n\n\n") // print("Finished an event") // print(currentEvents.count) completion(currentEvents) }) }) }) } } 

前面的代码使用此函数最终通过密钥从firebase中提取数据

 import Foundation import Firebase import FirebaseAuth struct EventService { static func show(forEventKey eventKey: String, eventCategory: String? = nil, completion: @escaping (Event?) -> Void) { // print(eventKey) let ref = Database.database().reference().child("events").child(eventKey) // print(eventKey) //pull everything ref.observeSingleEvent(of: .value, andPreviousSiblingKeyWith: { (snapshot,eventKey) in print(snapshot.value ?? "") guard let event = Event(snapshot: snapshot) else { return completion(nil) } if event.category == eventCategory{ completion(event) } if eventCategory == nil || eventCategory == "" || eventCategory == "Home" { completion(event) } }) } } 

我包含所有这些方法的唯一原因是为了更好地追踪正在发生的事情。 我上下查看了这些function,我似乎无法弄清楚是什么样的。 任何帮助表示赞赏。