Ios 处理Firebase查询中高元素计数导致的内存使用

Ios 处理Firebase查询中高元素计数导致的内存使用,ios,swift,firebase,firebase-realtime-database,Ios,Swift,Firebase,Firebase Realtime Database,我正在编写代码,将firebase中的元素添加到数组中,以使用textfield执行简单的搜索 该方法的代码如下所示: var filteredEvents = [Event]() var eventsArray = [Event]() fileprivate func fetchEvents(){ print("Fetching events....") //create a reference to the location in the database that you

我正在编写代码,将firebase中的元素添加到数组中,以使用textfield执行简单的搜索

该方法的代码如下所示:

 var filteredEvents = [Event]()
var eventsArray = [Event]()
fileprivate func fetchEvents(){
    print("Fetching events....")
    //create a reference to the location in the database that you want to pull from and observe the value there
    let ref = Database.database().reference().child("events")
    // this will retur a snapshot with all the data at that location in the database and cast the results as a dictionary for later use
    ref.observe(.value, with: { (snapshot) in
        guard let dictionaries = snapshot.value as? [String: Any] else{
            return
        }
        //does the job of sorting dictionary elements by key and value
        //displaying the key and each corresponding value
        dictionaries.forEach({ (key,value) in
           // print(key, value)
            //creating an eventDictionary to store the results of previous call
            guard let eventDictionary = value as? [String: Any] else{
                return
            }
            //will cast each of the values as an Event based off my included struct
            //Make sure to create a model it is the only way to have the data in the format you want for easy access
             let events = Event(currentEventKey: key, dictionary:eventDictionary)
            // appends that to the dictionary to create the dictionary of events
            self.eventsArray.append(events)
        })
        // will sort the array elements based off the name
        self.eventsArray.sort(by: { (event1, event2) -> Bool in
            return event1.currentEventName.compare(event2.currentEventName) == .orderedAscending
        })
        // will again reload the data
        self.collectionView?.reloadData()

    }) { (err) in
        print("Failed to fetch events for search")
    }
}
我个人没有想到我会有很多活动。我无法将所有1000多个事件添加到字典中。那会提高我的记忆力。无论如何,我都可以让查询响应文本字段。还有谁能帮我找到一行可以执行此操作但不会破坏我记忆的查询

"events" : {
"CCDS" : {
  "attend:count" : 1,
  "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 p.m.  Enjoy $5 cocktails, $4 wine, $3 beers and half-price appetizers at dozens and dozens of bars and restaurants.",
  "event:imageURL" :someURL",
  "event:location" : {
    "event:city" : "Philadelphia",
    "event:state" : "PA",
    "event:street:address" : "660 Chestnut St",
    "event:zip" : 19106
  },
  "event:name" : "Center City District Sips"
},
"MIA" : {
  "attend:count" : 1,
  "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" : "someURL",
  "event:location" : {
    "event:city" : "Philadelphia",
    "event:state" : "PA",
    "event:street:address" : "Ben Franklin Parkway",
    "event:zip" : 19130
  },
  "event:name" : "Made In America"
}
  },
例如,我想获取有关使用查询搜索的事件的所有信息。因此,如果我开始输入madeinAmerica,它将从events选项卡中获取有关该事件的所有相关信息

这就是我现在拥有的

fileprivate func fetchEvents(searchString: String){
    print("Fetching events....")
    //create a reference to the location in the database that you want to pull from and observe the value there
    let ref = Database.database().reference().child("events")
    // this will retur a snapshot with all the data at that location in the database and cast the results as a dictionary for later use
  let query = ref.queryOrdered(byChild: "event:name").queryEqual(toValue: searchString)
    print(query)
    query.observeSingleEvent(of: .value, with: { (snapshot) in
        guard let dictionary = snapshot.value as? [String: Any] else{
            print(snapshot.value)
            return
        }
        print(snapshot.value)
    }) { (err) in
        print("Failed to fetch event data", err)
    }

}
还这个

(/events{ep=美国制造;i=“event:name;sp=美国制造;})


看来问题是

"How can I query for a value contained in a child node?"
给出了一个与原作相似的结构

"events" : {
  "CCDS" : {
    "attend:count" : 1,
    "event:imageURL" :"someURL",
    "event:name" : "Center City District Sips"
  "MIA" : {
    "attend:count" : 1,
    "event:imageURL" : "someURL",
    "event:name" : "Made In America"
Firebase查询将返回所需的节点

如果用户输入madeinAmerica并点击search按钮,则查询将在快照中返回该节点

let searchString = "Made In America"
let ref = self.ref.child("events")
let query = ref.queryOrdered(byChild: "event:name").queryEqualTo(searchString)
query.observeSingleEvent(of: .value, with: { (snapshot) in
    for child in snapshot.children {
        let snap = child as! DataSnapshot
        let eventDict = snap.value as! [String: Any]
        let attendCount = eventDict["attend:count"] as! String
        let url = eventDict["event:imageURL"} as! String
    }
})
如果您想进行部分字符串匹配,用户可以只键入几个字符,如make,代码类似,但您需要让firebase返回所有以make开头的匹配

查询如下所示

let startString = "Made"
let endString = "Made" + "\\uf8ff"
let query = ref.queryOrdered(byChild: "event:name")
                        .queryStarting(atValue: startString)
                        .queryEnding(atValue: endString")
"events" : {
  "-uyuh8s8j8jsdas" : {
    "event": "CCDS"
    "attend:count" : 1,
    "event:imageURL" : "someURL",
  "-y88jsijsijjids" : {
    "event": "MIA"
    "attend:count" : 1,
    "event:imageURL" : "someURL",
   events_for_searching
       -uyuh8s8j8jsdas
         event:name: "Center City District Sips"
       -y88jsijsijjids
         event:name: "Made In America"
“\uf8ff”是Unicode中代码级别非常高的字符,因此它包含所有前面的字符

但是,查询“动态”可能会创建一个无响应或缓慢的UI,因此不建议这样做

另一种方法是创建一个单独的节点,其中包含的信息要少得多,并且包含用户将搜索的元素和对事件节点的引用

因此,包含所有数据的主节点如下所示

let startString = "Made"
let endString = "Made" + "\\uf8ff"
let query = ref.queryOrdered(byChild: "event:name")
                        .queryStarting(atValue: startString)
                        .queryEnding(atValue: endString")
"events" : {
  "-uyuh8s8j8jsdas" : {
    "event": "CCDS"
    "attend:count" : 1,
    "event:imageURL" : "someURL",
  "-y88jsijsijjids" : {
    "event": "MIA"
    "attend:count" : 1,
    "event:imageURL" : "someURL",
   events_for_searching
       -uyuh8s8j8jsdas
         event:name: "Center City District Sips"
       -y88jsijsijjids
         event:name: "Made In America"
“更小”的节点看起来像这样

let startString = "Made"
let endString = "Made" + "\\uf8ff"
let query = ref.queryOrdered(byChild: "event:name")
                        .queryStarting(atValue: startString)
                        .queryEnding(atValue: endString")
"events" : {
  "-uyuh8s8j8jsdas" : {
    "event": "CCDS"
    "attend:count" : 1,
    "event:imageURL" : "someURL",
  "-y88jsijsijjids" : {
    "event": "MIA"
    "attend:count" : 1,
    "event:imageURL" : "someURL",
   events_for_searching
       -uyuh8s8j8jsdas
         event:name: "Center City District Sips"
       -y88jsijsijjids
         event:name: "Made In America"
这样,您就可以将用于搜索的所有节点从events_加载到一个数组中(然后根据用户类型过滤数组),这将使UI非常响应,并且当用户选择一个名称时,您可以使用该节点的键作为参考,通过observeSingleEvent函数从events节点加载数据

编辑

作为对评论的回应,我想在代码中添加更多的细节

这是我的结构

  "events" : {
    "event_0" : {
      "event:name" : "An Event"
    },
    "event_1" : {
      "event:name" : "Made In America"
    }
  },
以及查询事件的代码:name:madeinAmerica

let searchString = "Made In America"
let ref = self.ref.child("events")
let query = ref.queryOrdered(byChild: "event:name").queryEqual(toValue: searchString)

query.observeSingleEvent(of: .value, with: { (snapshot) in
    guard let dictionary = snapshot.value as? [String: Any] else{
        print(snapshot.value)
        return
    }
    print(snapshot.value)
}) { (err) in
    print("Failed to fetch event data", err)
}
以及输出

Optional({
    "event_1" =     {
        "event:name" = "Made In America";
    };
})

为了澄清这一点,您是否在询问是否有一种方法可以在文本字段中输入一些值,然后查询数据库以查找该值?或者你想做一些类似于无限滚动的事情,一次下载几个孩子?@JenPerson我在寻找一种方法,在文本字段中输入一些值,然后查询firebase以查找该值,通知所有询问/编辑过你的问题的用户不是很好。请耐心等待,因为这是一个问答社区,而不是一个付费支持论坛。见,你需要提供更多的上下文。为什么需要下载数百个对象?如果用户对“房子”这个词进行搜索,你会根据某种排序算法(就像周围的每个搜索引擎一样)下载一些。在我看来,解决方法是使用基于页面的方法,在用户查询新术语时删除旧结果。@nathan我缺少什么上下文。我想减少我的问题在多个用户中可能遇到的内存问题,housesim不确定这意味着什么(/events{ep=Apples;I=“event:name;sp=Apples;})@SJackson5什么不起作用,你的第二条评论是什么意思?该代码或结构出现在哪里?在控制台中,当我打印querylike的结果时,当我打印snapshot.value以检查它是什么时,它从不打印SHMM。我回答中的代码是从一个正在工作的项目中复制和粘贴的,所以我知道它是有效的。我的回答中也有两个建议选项,所以我不知道您实现了哪一个。另外,我在你们的结构中没有看到任何关于苹果的东西,所以我不知道这是从哪里来的。我建议用新代码创建一个新问题,并确保包含包含Apple的Firebase结构。