enigrify
enigrify

Reputation: 301

How to keep certain changed properties unchanged in Realm migration - Swift

When you have a Realm model that looks something like:

class Thing: Object, Decodable {
  @objc dynamic var id: String = ""
  @objc dynamic var propertyOne: String = ""
  @objc dynamic var propertyTwo: String? = nil

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

All of the data is from a JSON file, using a JSON Serializer:

func serialize(input sourceName: String) {
    let path = Bundle.main.path(forResource: sourceName, ofType: nil)
    let url = URL(fileURLWithPath: path!)
    let jsonDecoder = JSONDecoder()
    do {
        let data = try Data(contentsOf: url)
        let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
        guard json is [AnyObject] else {
            assert(false, "failed to parse")
            return
        }
        do {
            let things = try jsonDecoder.decode([Thing].self, from: data)
            let realm = try! Realm()
            for thing in things {
                try! realm.write {
                    realm.add(thing)
                    // realm.add(thing, update: .modified) wipes out all changes
                }
            }
        } catch let error {
            print("failed to convert data: \(error)")
        }
    } catch let error {
        print(error)
    }
}

propertyOne's info is gotten from the JSON. propertyTwo's value is meant to be inputted from within the app. Once I serialize the JSON again, all changes to propertyTwo are wiped out. How do I make a migration without restoring it to the original JSON file? I want to keep some properties unchanged during a migration/new serialization.

In my AppDelegate, this is my code in didFinishLaunchingWithOptions:

let serializer = JSONSerializer()
serializer.serialize(input: "Nafliah.json")

This works if I have realm.add(thing, update: .modified) in my serializer. But this wipes out all changes made within the app. If I change it to this:

if save.bool(forKey: "serilized") == false {
    let serializer = JSONSerializer()
    serializer.serialize(input: "Nafliah.json")
    save.set(true, forKey: "serilized")
}

And make the serializer part realm.add(thing), it works and does not wipe out changed data every time the app is opened.

The issue is, once I add a new object to the JSON file, it obviously does not get added to the realm. I must serialize the JSON again. This, however, deletes all changes done in the 2 properties that are only meant to be changed by the user in the app.

Upvotes: 0

Views: 293

Answers (2)

enigrify
enigrify

Reputation: 301

I figured it out. You have to do a partial serialization.

Changed this:

realm.add(thing, update: .modified)

To:

realm.create(Thing.self, value: [
   "id": thing.id,
   "propertyOne": thing.propertyOne
   // Leave out propertyTwo to leave it unchanged
], update: .modified)

Upvotes: 1

Jagadeesh K
Jagadeesh K

Reputation: 121

Please check below link for Migrating Realm for existing properties

https://docs.realm.io/sync/v/3.x/using-synced-realms/migrating-your-data

Upvotes: 0

Related Questions