从Firebase Swift中检索信息的好方法

时间:2016-06-12 23:45:59

标签: ios swift firebase firebase-realtime-database

我的朋友和我正在开发一个关于swift的IOS项目与新的Firebase集成。我们能够写入Firebase数据库,但是我们在检索数据时遇到了问题。

我们有一个tableView控制器,我们希望从Firebase数据库填充该表。我们的数据库组织如下:

 <div class="container-fluid">
 <div class="row">
 <div class="col-md-2">
  <!--Sidebar content-->

   <p>
    Cauta:
    <input ng-model="$ctrl.query" />
   </p>

   <p>
    Sorteaza:
    <select ng-model="$ctrl.orderProp">
      <option value="name">Alfabetic</option>
    </select>
   </p>

 </div>
 <div class="col-md-10">
  <!--Body content-->

  <ul class="houses">
     <li ng-repeat="house in $ctrl.houses |
   filter:$ctrl.query | 
    orderBy:$ctrl.orderProp" class="thumbnail house-list-item">
      <a href="#!/houses/{{house.id}}" class="thumb">
        <img ng-src="{{house.imageUrl}}" alt="{{house.name}}" />
      </a>
      <a href="#!/houses/{{house.id}}">{{house.name}}</a>
      <p>{{house.price}}</p>
    </li>
  </ul>

 </div>
 </div>
 </div>

在项目中,我们创建了一个文件/类,它具有写入和从firebase检索的方法。如果我们想要从Firebase检索特定视图控制器的信息,我们只需从该类调用特定方法。

例如,这是该类中的一种方法:

root 
|  
- Movies
    |__ -Wjdkfdmlksdf (unique ID made by Firebase)
        |
        |_Actors
          |_A1 = ajkdfnadfdf
          |_A2 = podifpadsfipasdip
        |_Title = "Mission Impossible"
        |_DirectedBy = "Christopher McQuarrie"
-Actors
  |_ -ajkdfnadfdf (unique ID made by Firebase)
         |_name : "Tom Cruise"
         |_Birthday: xx/yy/zz

我们在func getListOfAllMovieIDs() -> [String] { let ref = FIRDatabase.database().reference(); var ListOfMovieIDS = [String](); ref.child("Movies").observeSingleEventOfType(.Value, withBlock: { (snapshot) in let postDict = snapshot.value as! [String : AnyObject] for (MID, _) in postDict { ListOfMovieIDS.append(MID); } }) { (error) in print(error.localizedDescription) } return listOfMoviesIDS } 的{​​{1}}中称之为上述方法。但是,该方法什么都不返回。我们还调用了另一种方法,比如获取actor的唯一IDS列表,也不返回任何内容。有什么建议吗?

3 个答案:

答案 0 :(得分:4)

Firebase异步加载数据。因此,您不会触发请求并等待以获取响应,而是发送请求,然后在某些时候会通知响应。

如果在代码中放置了一些位置很好的日志语句,就可以很容易地看到这一点:

func getListOfAllMovieIDs() {
    let ref = FIRDatabase.database().reference();
    print("Before listener");
    ref.child("Movies").observeSingleEventOfType(.Value, withBlock: { (snapshot) in
      print("Inside block");
    })
    print("After listener");
}

打印报表的顺序为:

  

听众之前

     

听众之后

     

内部块

因此,当您的功能退出时,数据尚未可用。这不是一个错误,而是一个非常有意的选择。通过允许代码继续,应用程序将保持对您的用户的响应。大多数现代互联网都使用这种模式,因此通常最好接受它(尽管最初的问题很棘手)。

解决方案通常是重新编写代码。我们不是说'#34;首先我们加载数据,然后我们做xyz&#34;,说它是&#34;我们开始加载数据,一旦我们得到它,我们做xyz&#34;。这就是Firebase数据加载方法占用块的原因:它包含&#34; xyz&#34;一旦数据可用就应该发生。

这样做的一个很好的副作用是,这个逻辑对于最初加载后可能更新的数据也很有用。当您使用objectEventOfType()时,您可以轻松处理情况,并且只要我们获取数据,就可以开始同步数据xyz&#34;并有一个处理实时更新的应用程序。

答案 1 :(得分:0)

尝试使用以下方法,因为当您使用observeSingleEventOfType方法时;返回初始数据后立即取消该块。这可能是您无法在回调块中看到结果的原因。

ref.observeEventType(.Value, withBlock: { snapshot in
    println(snapshot.value)
}, withCancelBlock: { error in
    println(error.description)
})

答案 2 :(得分:0)

  • 您只需更新以下功能,即可从数据库中获取所有电影ID:

    func getListOfAllMovieIDs() -> [String] { 
      let ref = FIRDatabase.database().reference();
      var ListOfMovieIDS = [String]();
      ref.child("Movies").observeSingleEventOfType(.Value, withBlock: { (snapshot) in           
        let postDict = snapshot.children.allObjects as? [DataSnapshot] {
        for (index ,movieDict) in postDict.enumerated() {
           let movieID = movieDict.key
           ListOfMovieIDS.append(movieID);
        }    
       }) { (error) in
          print(error.localizedDescription)
       }    
       return ListOfMovieIDS
    }