Append to array inside a Firebase Closure in Swift 3

佐手、 提交于 2019-12-26 12:29:10

问题


I am trying to append to an array inside a Firebase closure, I declared the array outside of the closure var CanJoinArray = [String]() But when I try to append to the array inside the closure: self.CanJoinArray.append("hello") and print it outside of the closure, print (CanJoinArray) it doesn't print. However, when I print the array inside the (inside) closure, it is able to append and print. How can I solve this? Thanks!

ref.observeSingleEvent(of: .value, with: { (FIRDataSnap) in
        for child in FIRDataSnap.children.allObjects {
            let key = (child as AnyObject).key as String
            self.myArray.append(key)
        }

        for (_, element) in self.myArray.enumerated() {
            self.ref.child(element).child("Players").observeSingleEvent(of: .value, with: { (Snap) in
                if Snap.childrenCount < 2 {
                    self.CanJoinArray.append("hello")
                }
                else {
                    print("Can't join lobby\(element)... Full!")
                }
                print(CanJoinArray) //this does work
            })
        }
       print (CanJoinArray) //this doesn't work
    })
}

The database Structure:

{
 "Lobbies" : {
    "RANDOMUUID" : {
       "LobbyName" : {
          "LobbyName" : ""
       },
       "Players" : {
          "user1" : "USERUID#"
       }
    }
 },
 "Users" : {
    "USERUID#" : {
      "DisplayName" : "user1"
    }
  }
}

回答1:


There are a couple of directions you can go...

It appears that you want to maintain a list of lobbies that are available, and the availability is determined by the number of players in the lobby. In this case 0 or 1 players means it's available and if 2 or more means it's full.

The first option that comes to mind is to change your structure by adding a is_available node within the lobby. When a player joins that lobby, add their uid to the players child and update the is_available to false if it's the second player. The structure would look something like this:

Lobbies
  lobby_id_0
    lobby_name: "lobby 5"
    is_available: false
    players
      uid_0: true
      uid_1: true
  lobby_id_1
    lobby_name: "lobby 12"
    is_available: true
    players
      uid_2: true
  lobby_id_2
    lobby_name: "some lobby"
    is_available: false
    players
      uid_3: true
      uid_4: true

The code would be a query:

let lobbiesRef = rootRef.child("Lobbies")
let queryRef = lobbiesRef.queryOrdered(byChild: "is_available").queryEqual(toValue: true)
queryRef.observeSingleEvent(of: .value, with: { (snapshot) in

    for child in snapshot.children {
       let snap = child as! FIRDataSnapshot
       let lobbyDict = snap.value as! [String: Any]
       let lobbyKey = snap.key
       self.availableLobbyArray.append(lobbyKey)
    }
})

This would add lobby_id_1 to the array as the other two lobbies each have two players.

A second solution is to keep second node that lists lobbies that are available.

Here's the All_Lobbies node and the Available_Lobbies node

All_Lobbies
   lobby_id_0
     lobby_name: "lobby 5"
     players
         uid_0: true
         uid_1: true
   lobby_id_1
     lobby_name: "lobby 12"
     players
        uid_2: true

Available_Lobbies
   lobby_id_1: true

Kind of the same concept; when a player joins lobby_id_1 and it's two players (so it's full), simply remove that lobby from the Available_Lobbies node.

The code to see which are available:

let availableLobbiesRef = rootRef.child("Available_Lobbies")
availableLobbiesRef.observeSingleEvent(of: .value, with: { (snapshot) in

    for child in snapshot.children {
       let snap = child as! FIRDataSnapshot
       let lobbyKey = snap.key
       self.availableLobbyArray.append(lobbyKey)
    }
})

The advantage of this structure is two-fold. We eliminate the query completely because only available lobbies are stored in that node. Queries are much 'heavier' than an observe and take more resources. The second thing is that if there are 1 Million Available_Lobbies, we are loading in far less data!




回答2:


Just move the print statement up one maybe,

 for (_, element) in self.myArray.enumerated() {

        self.ref.child(element).child("Players").observeSingleEvent(of: .value, with: { (Snap) in

            if Snap.childrenCount < 2 {
                self.CanJoinArray.append("hello")

            }
            else {
                print("Can't join lobby\(element)... Full!")

            }


        })

      print (CanJoinArray)

    }

  you were here

})


来源:https://stackoverflow.com/questions/42486321/append-to-array-inside-a-firebase-closure-in-swift-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!