提问人:Max 提问时间:8/3/2023 最后编辑:Joakim DanielsonMax 更新时间:8/3/2023 访问量:70
如何在CoreData中从Firebase Realtime获取数据?
How to fetch data from Firebase Realtime in CoreData?
问:
我是 CoreData 的新手,不了解如何从 Firebase Realtime 到 CoreData 写入和读取数组。
你能告诉我如何正确地将数组从 Firebase 获取到 CoreData 吗? 这是 FirebaseController:
final class FirebaseController: ObservableObject {
@Published var birds = [Bird]()
@Published var places = [Place]()
private lazy var databaseDB: DatabaseReference? = {
let reference = Database.database().reference().child("db")
return reference
}()
private lazy var birdsDB: DatabaseReference? = {
let reference = Database.database().reference().child("db").child("birds")
return reference
}()
private lazy var placesDB: DatabaseReference? = {
let reference = Database.database().reference().child("db").child("places")
return reference
}()
private let context = PersistenceController.shared.viewContext
init() {
listentoRealtimeDatabase()
}
func listentoRealtimeDatabase() {
guard let dbBirds = birdsDB else {
return
}
guard let dbPlaces = placesDB else {
return
}
dbBirds
.observe(.childAdded) { [weak self] snapshot, context in
guard
let self = self,
var json = snapshot.value as? [String: Any]
else {
return
}
json["id"] = snapshot.key
do {
let birdData = try JSONSerialization.data(withJSONObject: json)
let decoder = JSONDecoder(context: self.context)
let bird = try decoder.decode(Bird.self, from: birdData)
print("success \(String(describing: bird.name!)) \ (String(describing: bird.imageURL!))")
if !self.birds.contains(where: { $0.name == bird.name }) {
self.birds.append(bird)
save()
}
print("Count: \(birds.count)")
}
catch { print(error)
}
}
dbPlaces
.observe(.childAdded) { [weak self] snapshot, context in {
guard
let self = self,
var json = snapshot.value as? [String: Any]
else {
return
}
json["id"] = snapshot.key
do {
let placeData = try JSONSerialization.data(withJSONObject: json)
let decoder = JSONDecoder(context: self.context)
let place = try decoder.decode(Place.self, from: placeData)
print("success \(String(describing: place.id!))")
if !self.places.contains(where: { $0.id == place.id }) {
self.places.append(place)
print(place.placeName)
save()
}
print("Count: \(places.count)")
}
catch { print(error)
}
}
// получаем данные из CoreData
getBirdsFromCoreData()
getPlacesFromCoreData()
}
}
func getBirdsFromCoreData() {
let request = Bird.fetchRequest()
request.returnsObjectsAsFaults = false
if let results = try? self.context.fetch(request) {
self.birds = results
}
}
func getPlacesFromCoreData() {
let request = Place.fetchRequest()
request.returnsObjectsAsFaults = false
if let results = try? self.context.fetch(request) {
self.places = results
}
print(places.count)
}
func stopListening() {
databaseDB!.removeAllObservers()
}
func deleteRecord(indexSet: IndexSet) {
let itemToDelete = birds[indexSet.first!]
context.delete(itemToDelete)
save()
getBirdsFromCoreData()
getPlacesFromCoreData()
}
private func save() {
guard context.hasChanges else { return }
do {
try context.save()
print("Saved changes.")
} catch {
print("Could not save changes in context: \(error)")
}
}
}
和 CoreData 类: 在 Places 中,我不清楚如何正确处理数组,您能告诉我如何做到这一点吗?
@objc(Bird)
public class Bird: NSManagedObject, Identifiable, Codable {
enum CodingKeys: String, CodingKey {
case imageURL
case name
}
static let managedObjectContext = CodingUserInfoKey(rawValue: "managedObjectContext")
@nonobjc public class func fetchRequest() -> NSFetchRequest<Bird> {
return NSFetchRequest<Bird>(entityName: "Bird")
}
@NSManaged public var id: String?
@NSManaged public var name: String?
@NSManaged public var imageURL: String?
@NSManaged public var places: NSSet?
public var birdPlases: [Place] {
let placesSet = self.places as? Set<Place> ?? []
return placesSet.sorted {
$0.placeName > $1.placeName
}
}
public var birdName: String {
return name ?? ""
}
public var image: String {
return imageURL ?? ""
}
public required convenience init(from decoder: Decoder) throws {
guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else { fatalError("Error: with managed object context!") }
let entity = NSEntityDescription.entity(forEntityName: "Bird", in: context)!
self.init(entity: entity, insertInto: context)
let values = try decoder.container(keyedBy: CodingKeys.self)
name = try values.decode(String.self, forKey: .name)
imageURL = try values.decode(String.self, forKey: .imageURL)
}
// MARK: - Encodable
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .name)
try container.encode(imageURL, forKey: .imageURL)
}
}
extension CodingUserInfoKey {
static let context = CodingUserInfoKey(rawValue: "context")!
}
extension JSONDecoder {
convenience init(context: NSManagedObjectContext) {
self.init()
self.userInfo[.context] = context
}
}
extension Bird {
@objc(addPlaceObject:)
@NSManaged public func addToPlaces(_ value: Place)
@objc(removePlaceObject:)
@NSManaged public func removeFromPlaces(_ value: Place)
@objc(addEmployees:)
@NSManaged public func addToPlaces(_ value: NSSet)
@objc(removeEmployees:)
@NSManaged public func removeFromPlaces(_ value: NSSet)
}
@objc(Place)
public class Place: NSManagedObject, Identifiable, Codable {
enum CodingKeys: String, CodingKey {
case names
}
@nonobjc public class func fetchRequest() -> NSFetchRequest<Place> {
return NSFetchRequest<Place>(entityName: "Place")
}
@NSManaged public var id: UUID?
@NSManaged public var names: Data?
// public var placeName: String {
// return name ?? ""
// }
public required convenience init(from decoder: Decoder) throws {
guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else { fatalError("Error: with managed object context!") }
let entity = NSEntityDescription.entity(forEntityName: "Place", in: context)!
self.init(entity: entity, insertInto: context)
let values = try decoder.container(keyedBy: CodingKeys.self)
names = try values.decode(Data.self, forKey: .names)
}
// MARK: - Encodable
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(names, forKey: .names)
}
}
答: 暂无答案
评论