Сохранение массива в Firebase

Я использую Firebase 3.0 в качестве бэкэнда, и мне нужно сохранять всеuser.uid в отдельном дочернем элементе, который должен быть NSArray, а затем получить этот массив с помощью цикла for!

Вот как я сохраняю свои данные: я создал отдельный класс для FIRController, который обрабатывает все хранение и извлечение базы данных и хранилища.

func signUpUserWithBasicInfo(emailId : String! , password : String!, username : String!, age : String, gender : String!, backpackerType : String, info : [String : AnyObject], completionBlock : (() -> Void)){

    print("fir signup did recieve")
    FIRAuth.auth()?.createUserWithEmail(emailId, password: password, completion: {
        user,error in

        if error != nil{
            print("error encountered while backend email signup Handshake : \(error)")
            print("")
            self.delegate.firShowAlert("Error signing you up", Message: "Please check your network or this email already exist!")

        }else{
            print("uploading database")
            self.profilePictureUploading(info, completionBlock: {

                FIRControllerClass.ref.child("UserProfile").child(user!.uid).setValue([
                    "username" : username,
                    "email" : emailId,
                    "age" : age,
                    "gender" : gender,
                    "password" : password,
                    "typeOfBackpacker" : backpackerType
                    ])

                completionBlock()

            })
        }
    })
}

func profilePictureUploading(infoOnThePicture : [String : AnyObject],completionBlock : (()->Void)) {

    if let referenceUrl = infoOnThePicture[UIImagePickerControllerReferenceURL] {
        print(referenceUrl)
        let assets = PHAsset.fetchAssetsWithALAssetURLs([referenceUrl as! NSURL], options: nil)
        print(assets)
        let asset = assets.firstObject
        print(asset)
        asset?.requestContentEditingInputWithOptions(nil, completionHandler: { (ContentEditingInput, infoOfThePicture)  in

            let imageFile = ContentEditingInput?.fullSizeImageURL
            print("imagefile : \(imageFile)")

            let filePath = FIRAuth.auth()!.currentUser!.uid +  "/\(Int(NSDate.timeIntervalSinceReferenceDate() * 1000))/\(imageFile!.lastPathComponent!)"
            print("filePath : \(filePath)")

                FIRControllerClass.storageRef.child("ProfilePictures").child(filePath).putFile(imageFile!, metadata: nil, completion: { (metadata, error) in

                         if error != nil{

                            print("error in uploading image : \(error)")
                            self.delegate.firShowAlert("Error Uploading Your Profile Pic", Message: "Please check your network!")
                         }

                          else{

                                print("metadata in : \(metadata!)")
                                print(metadata?.downloadURL())
                                print("The pic has been uploaded")
                                print("download url : \(metadata?.downloadURL())")

                                self.uploadSuccess(metadata!, storagePath: filePath)

                                completionBlock()

                }

            })
        })

    } else {
            print("No reference URL found!")
    }
}

Как мне создать дочерний элемент в моем бэкэнде, который будет служить массивом, и как я могу получить этот массив?

Моя огненная база JSON СТРУКТУРА: -

{
  "UserId" : [ 1, 
    "Sq5EDvVOsQWkLylEx3GrBdEsIN92",
    "xC4jCJmobUcqghq8C3SI1XT0UPk1",
    "D8QmnOSH6vRYiMujKNXngzhdn992",
    "riHjon6wknOmALwf0Z0Ri5aOMA82",
    "fKqlb88MKsYCE43xy7D51qH6jqH3",
    "aCgAFAGDIgWRSUu9a2aMo9HtnnD3",
    "iicKACGo8RaeTSEggKPB0sU2Bme2",
    "qJ2c8AcEYzVkJKLl13N92tyKnbz2"
    ],
  "UserProfile" : {
    "D8QmnOSH6vRYiMujKNXngzhdn992" : {
      "age" : "12",
      "email" : "[email protected]",
      "gender" : "f",
      "password" : "123454321",
      "typeOfBackpacker" : "dummy",
      "username" : "duummyy1"
    },
    "Sq5EDvVOsQWkLylEx3GrBdEsIN92" : {
      "age" : "121",
      "email" : "[email protected]",
      "gender" : "gjhg",
      "password" : "123454321",
      "typeOfBackpacker" : "chef",
      "username" : "hgfgh"
    },
    "aCgAFAGDIgWRSUu9a2aMo9HtnnD3" : {
      "age" : "24",
      "email" : "[email protected]",
      "gender" : "F",
      "password" : "123454321",
      "typeOfBackpacker" : "Group",
      "username" : "Cathy"
      },
      etc
}

мне также нужно добавить массивno of friends в моей базе данных (массиве). Единственная причина, по которой я использую цикл for, заключается в том, что я могу отображать данные каждого пользователя для моего пользователя (кроме него самого), используя массив userId, который я создал в моей базе данных, которые на самом деле родительский узел для каждой моей соответствующей пользовательской базы данных.

Вот как я добавляюUserId в моей базе данных: -

func retrieveUserIdsArray(completionBlock : ((appendedArr : NSMutableArray) -> Void)){

    var appendedArray : NSMutableArray = []

    FIRControllerClass.ref.child("UserId").observeEventType(FIRDataEventType.Value, withBlock: {(snapshot) in

        if let userIdDetails = snapshot.value as? NSMutableArray{

        userIdDetails.addObject((FIRAuth.auth()?.currentUser?.uid)!)
        appendedArray = userIdDetails

        completionBlock(appendedArr: appendedArray)

        }
    })
} 

который вызывается в этой функции:

    func signUpUserWithBasicInfo(emailId : String! , password : String!, username : String!, age : String, gender : String!, backpackerType : String, info : [String : AnyObject], completionBlock : (() -> Void)){

    print("fir signup did recieve")

    FIRAuth.auth()?.createUserWithEmail(emailId, password: password, completion: {
        user,error in

        if error != nil{

            print("error encountered while backend email signup Handshake : \(error)")

            print("")

            self.delegate.firShowAlert("Error signing you up", Message: "Please check your network or this email already exist!")

        }else{

            print("uploading database")

            self.profilePictureUploading(info, completionBlock: {

                FIRControllerClass.ref.child("UserProfile").child(user!.uid).setValue([
                    "username" : username,
                    "email" : emailId,
                    "age" : age,
                    "gender" : gender,
                    "password" : password,
                    "typeOfBackpacker" : backpackerType
                    ])


                var a = 0

                self.retrieveUserIdsArray({ (appendedArr) in

                    a += 1

                    print("The appended array is : \(appendedArr)")

                    if a == 1{

                        FIRControllerClass.ref.child("UserId").setValue(appendedArr)

                    }else{

                        completionBlock()

                    }
                })
            })
        }
    })
}

Причина, почему я использовалa переменная для решения бесконечного цикла, который он вызывал (на данный момент я знаю, что это просто взломать ...)

Открыт для любого лучшего способа справиться с этим! ..

 Jay15 июл. 2016 г., 19:00
Там может быть лучший способ сделать это. Можете ли вы опубликовать образец вашей структуры Firebase, чтобы мы могли увидеть, что у вас есть сейчас? Пожалуйста, отправьте как текст, без изображений. Вы можете получить это через Консоль Firebase-> Три точки справа-> Экспорт JSON.
 Jay14 июл. 2016 г., 21:25
Массивы могут быть очень сложными в Firebase (или любой базе данных NoSQL), и их использование очень ситуативно, так как обычно есть лучшие варианты для хранения данных. Кроме того, чтение данных из Firebase в for..loop не является хорошей идеей, поскольку позволяет обойти асинхронную природу Firebase. Можете ли вы предоставить вариант использования для использования массивов таким образом?
 Dravidian15 июл. 2016 г., 01:07
Я хочу сохранить идентификаторы моих пользователей в определенном массиве, чтобы я мог показать их данные в разделе «Найти друзей»! ... Я сохраняю их личную базу данных в их уникальном user.uid как дочерний узел «UserProfile». , мне нужно получить доступ ко всей базе данных сразу на одной странице и применить алгоритм геолокации и механизм рекомендаций на другой странице ... вот почему мне нужен массив, в котором я могу хранить все уникальные идентификаторы моего пользователя.

Ответы на вопрос(1)

Решение Вопроса

так как отдельные элементы не могут быть доступны напрямую или изменены. Вы либо читаете весь массив, либо пишете весь массив.

Я бы предложил изменить структуру, чтобы она лучше соответствовала нужным данным и полностью избегала массивов:

"UserProfile" : {
    "D8QmnOSH6vRYiMujKNXngzhdn992" : {
      "age" : "12",
      "email" : "[email protected]",
      "gender" : "f",
      "password" : "123454321",
      "typeOfBackpacker" : "dummy",
      "username" : "duummyy1"
      "friend_count": 10
      "friend_of"
         "aCgAFAGDIgWRSUu9a2aMo9HtnnD3": true
    },

тогда простой глубокий запрос вернет все, что вам нужно (Firebase v2)

let myUid = "aCgAFAGDIgWRSUu9a2aMo9HtnnD3"
let path = ("friend_of/\(myUid)") // equals friend_of/aCgAFAGDIgWRSUu9a2aMo9HtnnD3
var userIdArray = [String]()
userProfileRef.queryOrderedByChild(path)
              .queryEqualToValue(true)
              .observeSingleEventOfType(.Value, withBlock: { snapshot in
   for child in snapshot.children {
      let userId = child.key as String
      userIdArray.append(userId)
   }
   //loop is done, now we have an array of userIds that are friends
})

Код возвращает каждого пользователя, который является моим другом (myUid)

Я также добавил узел подсчета друзей, который просто ведет подсчет количества друзей этого пользователя. Когда добавлен друг, увеличьте значение, а при удалении уменьшите. Это быстро

myUid.child("friend_count").setValue(updated_count)

Этот код также избегает циклов, обратных вызовов и дополнительных блоков завершения, потому что он использует Firebase для получения данных и дает нам знать, когда это будет сделано.

Если вы действительно хотите прочитать узел массива (не рекомендуется)

    let myRef = self.myRootRef.child("array_node")
    myRef.observeSingleEventOfType(.Value, withBlock: { snapshot in

        let a = snapshot.value as! NSArray
        print(a) //a an NSArray

        let b = (a as Array).filter {$0 is String}

        print(b) //b is a Swift Array

        print( b[1] )
    })
 Dravidian17 июл. 2016 г., 15:29
let myUid = "aCgAFAGDIgWRSUu9a2aMo9HtnnD3" это то, что вы жестко запрограммировали, и мне нужно иметь каждый user.uid для заполнения моего tableView. Именно по этой причине я изначально хранил uid каждого пользователя в массиве. Кстати, спасибо за помощь!
 Jay17 июл. 2016 г., 16:40
@AchintyaGupta Я жестко закодировал это как пример uid. Это будет идентификатор пользователя, вошедшего в систему в данный момент, полученного из переменной авторизации Firebase.

Ваш ответ на вопрос