简体   繁体   中英

Realm and Parse integration: how to save the realm

I'm trying to create a bundle realm for my application. I thought it should be quite simple. Since I already have all needed records in Parse, I just have to:

  • create realm models and objects
  • load parse records to realm objects
  • save the realm

So, I created two realm models:

class RealmContainer : Object {
    dynamic var rContainerId: String! //should be equal objectId from Parse
    dynamic var rContainerName: String! //should be equal "name" field from Parse
  ...
    var messages = List<RealmMessage>()

    override static func primaryKey() -> String? {
        return "rContainerId"
    }
}

and

class RealmMessage : Object {
    dynamic var rMessageId: String!
    ...
    dynamic var rParentContainer: RealmContainer!
}

Getting results from Parse seems to be working. Also my realm objects are also good

    var allUserContainers: [RealmContainer] = [] 

I was able to populate this array with values from Parse. But when I'm trying to save this realm, I'm getting a) nothing or b) error message

My code (this one'll get nothing):

let realm = try! Realm()
try! realm.write {
    realm.add(self.allUserContainers[0])
    print(Realm().path)
    print(realm.path)
    }

My code (this one'll get nothing too):

let realm = try! Realm()
try! realm.write {
    realm.create(RealmContainer.self, value: self.allUserContainers[0], update: true)
    print(Realm().path)
    print(realm.path)
    }

My code 3 (this will get me an error message " Terminating app due to uncaught exception 'RLMException', reason: 'Illegal recursive call of +[RLMSchema sharedSchema]. Note: Properties of Swift Object classes must not be prepopulated with queried results from a Realm "):

//from firstViewController, realm is a global variable
let realm = try! Realm()

//another swift module
    try! realm.write {
        realm.create(RealmContainer.self, value: self.allUserContainers[0], update: true)
        print(Realm().path)
        print(realm.path)
        }

Obviously I don't properly understand how it should work, but I tried several swift/realm tutorials and they were actually straightforward. So, what did I do wrong?

Update

So, I updated my code to make it as much simple/readable as possible. I have a Dog class, and I am trying to get Dogs from Parse and put them to Realm.

AppDelegate.swift

let realm = try! Realm() //global

Dog.swift

class Dog : Object {
    dynamic var name = ""
    dynamic var age = 0
}

User.swift (getDogs and putDogs functions)

class User {
    var newDogs:[Dog] = []
...

func getDogs() {
    self.newDogs = []

    let dogsQuery = PFQuery(className: "Dogs")
    dogsQuery.limit = 100
    dogsQuery.findObjectsInBackgroundWithBlock { (currentModes, error) -> Void in
        if error == nil {

            let tempModes:[PFObject] = currentModes as [PFObject]!

            for var i = 0; i < tempModes.count; i++ {
                let temp = Dog()
                temp.name = currentModes![i]["dogName"] as! String
                self.newDogs.append(temp)

            }

        } else {
            print("something happened")
        }
        }
}

...

func putDogs() {

    print(self.newDogs.count)
    try! realm.write({ () -> Void in
        for var i = 0; i < newDogs.count; i++ {
            realm.add(newDogs[i])
        }

    })
        try! realm.commitWrite() //doesn't change anything
    }

error message still the same:

Terminating app due to uncaught exception 'RLMException', reason: 'Illegal recursive call of +[RLMSchema sharedSchema]. Note: Properties of Swift Object classes must not be prepopulated with queried results from a Realm

I believe I just have some global misunderstanding about how Realm is working because it is extremely simple configuration.

About your RealmSwift code : You have implemented it right.

When you declare a class of realm in swift, it's a subclass of Object class. Similarly for the parse it's subclass of PFObject .

You custom class have to have only one base class. So can't use functionalities of both the libraries Parse as well as Realm.

If you have to have use both Parse and Realm, you need to declare two different classes like RealmMessage and ParseMessage .

Retrieve data for ParseMessage from parse and copy properties to RealmMessage.

Why you want to use both Parse and Realm ? parse also provides local data store by just writing Parse.enableLocalDatastore() in appDelegate before

Parse.setApplicationId("key",
            clientKey: "key")

Your Realm Swift code seems fine. Realm is very flexible when creating objects using (_:value:update:) , in being able to take in any type of object that supports subscripts. So you could even directly insert PFObject if the schemas matched.

The problem seems to be how you're populating the allUserContainers array. As the error says, you cannot fetch a Realm Object from Realm and then try and re-add it that way. If you're trying to update an object already in Realm, as long as the primary key properties match, you don't need to supply the whole object back again.

Can you please revisit the logic of how your allUserContainers variable is being populated, and if you can't fix it, post the code into your question?

Sidenote: You probably don't need to define your Realm properties as implicitly unwrapped as well. This is the recommended pattern:

class RealmContainer : Object {
    dynamic var rContainerId = ""
    dynamic var rContainerName = ""
}

Actually I found what was wrong: as i suspected it was a stupid mistake, some property in my class was UIImage type, and Realm just can't work with this type (even if I'm not trying to put objects of this class into realm). So, my bad. I am slightly embarassed by it, but will not delete my question because error messages from Realm were not very understandable in this case

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM