【问题标题】:Storing custom objects with array of custom objects in Firebase: Swift在 Firebase 中使用自定义对象数组存储自定义对象:Swift
【发布时间】:2019-07-28 19:18:46
【问题描述】:

如何使用 Swift 在 Firebase 实时数据库中实现此设置:

数据库层次结构

目前,我通过将较大的元素(具有 familyKey、geofences 和 phoneNumbers 属性)存储为自定义对象来做到这一点。此外,geofences 属性本身是一组自定义对象。我得到一个 NSException 以所描述的方式执行此操作。我该怎么做呢?

    var tempGeofences = [GeofenceData]()
    tempGeofences.append(GeofenceData(name: "Hello WOrld", latitude: 0, longitude: 0, radius: 1000))

    let familyKey:String = String(Int.random(in: 1000...99999))
    let uid:String = Auth.auth().currentUser!.uid
    let phoneNumber = "1111111111"
    let parent = Parent(phoneNumber: phoneNumber, familyKey: familyKey, geofences: tempGeofences)

    databaseRef.child(uid).setValue(parent)

NSException 在这一行被抛出:

databaseRef.child(uid).setValue(parent)

父类:

import Foundation

public class Parent {
var phoneNumber: String?
var familyKey: String?
var geofences: [GeofenceData]?

init() {
    self.phoneNumber = ""
    self.familyKey = ""
    self.geofences = nil
}

init(phoneNumber: String?, familyKey: String?, geofences:[GeofenceData]) {
    self.phoneNumber = phoneNumber
    self.familyKey = familyKey
    self.geofences = geofences
}

public func getPhoneNumber() -> String {
    return phoneNumber!
}

public func getFamilyKey() -> String {
    return familyKey!
}

public func getGeofences() -> [GeofenceData] {
    return geofences!
}

// left off here, trying to send geofence object to firebase
public func toDictionary() -> Any {
    return ["familyKey": familyKey, "geofences": geofences, "phoneNumber": phoneNumber]
}

}

还有 GeofenceData 类:

import Foundation
import Firebase

public class GeofenceData {
var name: String?
var latitude: Double?
var longitude: Double?
var radius: Float?

init() {

}

init(name: String?, latitude: Double, longitude: Double, radius: Float) {
    self.name = name
    self.latitude = latitude
    self.longitude = longitude
    self.radius = radius
}

// left off here, trying to send geofence object to firebase
public func toDictionary() -> Any {
    return ["name": name, "latitude": latitude, "longitude": longitude, "radius": radius]
}

public func getName() -> String {
    return name!
}

public func getLatitude() -> Double {
    return latitude!
}

public func getLongitude() -> Double {
    return longitude!
}

public func getRadius() -> Float {
    return radius!
}

public func setName(name: String?) {
    self.name = name
}

public func saveToFirebase(reference: DatabaseReference) {
    let dict = ["name": name, "latitude": latitude, "longitude": longitude, "radius": radius] as Any
    reference.child("geofences").child("0").setValue(dict)
}

}

【问题讨论】:

  • 请添加您有问题的代码,并说明您在哪里得到 NSException,以便我们为您提供帮助。
  • 嗨 Bhaumik,我现在不在城里,但我可以为您提供尽可能详细的信息。基本上,我有一个具有familyKey、geofences 和phoneNumber 属性的类,其中geofences 是另一个自定义对象的数组,它具有经度、纬度、名称和半径属性。 NSException 被抛出在我通过 setValue(object) 将数据保存到 firebase 的行上
  • 该错误是因为您无法在 Firebase 中存储用户定义的对象,或者 object 为 nil。但是,没有看到您的代码,我们只是在猜测。请花点时间查看How do I ask a good question? 和How to create a Minimal, Complete, and Verifiable example。用您的代码更新您的问题,我们会看看!
  • 嗨,我刚刚更新了我的帖子!
  • 如您所见,在 GeofenceData 对象的 saveToFirebase() 函数中,我必须硬编码索引 0 才能在 Firebase 中创建 GeofenceData 对象数组。在 Android 中,我可以只执行“setValue(parent)”,它会工作得很好。

标签: ios swift firebase firebase-realtime-database


【解决方案1】:

Parent 不是 Firebase 识别的对象,因此会引发错误。

Firebase 指南Reading & Writing Data 显示了可以编写的四种类型的对象;字符串、数字、字典、数组。

一种解决方案是在类中构建一个函数,返回您要写入的数据。

public class Parent {
    var phoneNumber: String?
    var familyKey: String?
    var geofences: [GeofenceData]?

    init() {
        self.phoneNumber = ""
        self.familyKey = ""
        self.geofences = nil
    }

    //other init functions

    func getParentDict() -> [String: Any] {

        let geoDict = ["name": name,
                       "latitude": latitude,
                       "longitude": longitude,
                       "radius": radius
        ]

        let zeroNode = ["0": geoDict]

        let dictForFirebase: [String: Any] = [
            "phoneNumber": phoneNumber,
            "familyKey": familyKey,
            "geofences": zeroNode
        ]

        return dictForFirebase
    }
}

在实践中

var tempGeofences = [GeofenceData]()
tempGeofences.append(GeofenceData(name: "Hello WOrld", latitude: 0, longitude: 0, radius: 1000))

let familyKey:String = String(Int.random(in: 1000...99999))
let uid:String = Auth.auth().currentUser!.uid
let phoneNumber = "1111111111"
let parent = Parent(phoneNumber: phoneNumber, familyKey: familyKey, geofences: tempGeofences)
let parentDict = parent.getParentDict
databaseRef.child(uid).setValue(parentDict)

但是,一个问题是子节点以“0”作为键。看起来您可能正在使用数组。如果有充分的理由,那很好,但在 NoSQL 数据库中使用数组通常有更好的选择。请参阅名为 Arrays Are Evil

的旧版但仍然准确的 Firebase 帖子

编辑:

根据评论/问题“如何在“0”节点之后添加另一个子节点”

假设我们知道父节点 qSaEE...,让我们添加一个“1”节点

let parentNode = "qSaEE..."
let geofenceRef = firebaseRef.child(parentNode).child("geofences")

let geoDict = ["name": name,
               "latitude": latitude,
               "longitude": longitude,
               "radius": radius
               ]

let oneNode = ["1": geoDict]

geofenceNode.setValue(oneNode)

【讨论】:

  • 嗨 Jay,当我从 Android 上传 Parent 对象时,它会自动添加“0”节点,看到“geofences”是一个 GeofenceData 对象数组。要并行 android,我需要为 iOS 复制这个数据库结构。我该怎么做?
  • 另外,在我更大的节点中,我的三个属性是familyKey、geofences 和phoneNumber。你提供的设置不会给我familyKey、0和phoneNumber三个属性吗?
  • 最后一件事,我希望 Parent 对象能够容纳多个 GeofenceData 对象,因此我使用 GeofenceData 对象数组作为 Parent 的属性。在上面的示例中,我们只为一个地理围栏数据创建一个字典并将其存储在节点“0”下。我如何使它足够灵活,所以如果我想稍后添加到该数组中,我可以在节点“0”下添加另一个 GeofenceData 对象?很抱歉给您带来麻烦。
  • @pavpanda 我错过了那个 0 节点,所以我更新了代码以提供确切的结构。
  • @pavpanda 我更新了它以回答您关于在“0”节点之后添加另一个节点的第二个问题
猜你喜欢
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多